From e0c6872cf40896c7be36b11dcc744620f10adf1d Mon Sep 17 00:00:00 2001 From: Norbert Preining Date: Mon, 2 Sep 2019 13:46:59 +0900 Subject: Initial commit --- macros/latex/contrib/siunitx/README.md | 55 + macros/latex/contrib/siunitx/siunitx.dtx | 18021 +++++++++++++++++++++++++++++ macros/latex/contrib/siunitx/siunitx.pdf | Bin 0 -> 612110 bytes 3 files changed, 18076 insertions(+) create mode 100644 macros/latex/contrib/siunitx/README.md create mode 100644 macros/latex/contrib/siunitx/siunitx.dtx create mode 100644 macros/latex/contrib/siunitx/siunitx.pdf (limited to 'macros/latex/contrib/siunitx') diff --git a/macros/latex/contrib/siunitx/README.md b/macros/latex/contrib/siunitx/README.md new file mode 100644 index 0000000000..93244686b6 --- /dev/null +++ b/macros/latex/contrib/siunitx/README.md @@ -0,0 +1,55 @@ +siunitx - A comprehensive (SI) units package +============================================== + +Physical quantities have both numbers and units, and each +physical quantity should be expressed as the product of a number +and a unit. Typesetting physical quantities requires care to +ensure that the combined mathematical meaning of the number-unit +combination is clear. In particular, the SI units system lays +down a consistent set of units with rules on how these are to be +used. However, different countries and publishers have differing +conventions on the exact appearance of numbers (and units). The +`siunitx` package provides a set of tools for authors to typeset +quantities in a consistent way. The package has an extended set +of configuration options which make it possible to follow +varying typographic conventions with the same input syntax. The +package includes automated processing of numbers and units, and +the ability to control tabular alignment of numbers. + +Installation +------------ + +The package is supplied in `dtx` format and as a pre-extracted +zip file, `siunitx.tds.zip`. The later is most convenient for +most users: simply unzip this in your local texmf directory . If +you want to unpack the `.dtx` yourself, running `tex +siunitx.dtx` will extract the package whereas `latex +siunitx.dtx` will extract it and also typeset the documentation. + +The package requires LaTeX3 support as provided in the +`l3kernel` and `l3packages` bundles. Both of these are available +on [CTAN](http://www.ctan.org/) as ready-to-install zip files. +Suitable versions are available in MiKTeX 2.9 and TeX Live 2015 +(updating the relevant packages online may be necessary). +LaTeX3, and so `siunitx`, requires the e-TeX extensions: these +are available on all modern TeX systems. + +Typesetting the documentation requires a number of packages in +addition to those needed to use the package. This is mainly +because of the number of demonstration items included in the +text. To compile the documentation without error, you will +need the packages: + - `amsmath` + - `booktabs` + - `cancel` + - `caption` + - `cleveref` + - `colortbl` + - `csquotes` + - `datatool` + - `helvet` + - `mathpazo` + - `multirow` + - `listings` + - `pgfplots` + - `xcolor` \ No newline at end of file diff --git a/macros/latex/contrib/siunitx/siunitx.dtx b/macros/latex/contrib/siunitx/siunitx.dtx new file mode 100644 index 0000000000..9fc30aa992 --- /dev/null +++ b/macros/latex/contrib/siunitx/siunitx.dtx @@ -0,0 +1,18021 @@ +% \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 2015 +(updating the relevant packages online may be necessary). +LaTeX3, and so `siunitx`, requires the e-TeX extensions: these +are available on all modern TeX systems. + +Typesetting the documentation requires a number of packages in +addition to those needed to use the package. This is mainly +because of the number of demonstration items included in the +text. To compile the documentation without error, you will +need the packages: + - `amsmath` + - `booktabs` + - `cancel` + - `caption` + - `cleveref` + - `colortbl` + - `csquotes` + - `datatool` + - `helvet` + - `mathpazo` + - `multirow` + - `listings` + - `pgfplots` + - `xcolor` +% +%<*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-2018 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.md}{\from{\jobname.dtx}{readme}} +} +\ifx\fmtname\nameofplainTeX + \expandafter\endbatchfile +\else + \expandafter\endgroup +\fi +% +%<*driver|package> +\RequirePackage{expl3}[2015/09/11] +\RequirePackage{xparse} +% +%<*driver> +\documentclass{l3doc} +\usepackage[german,french,spanish,UKenglish]{babel} +\usepackage[table]{xcolor} +\usepackage{amsmath,booktabs,cancel,caption,colortbl,csquotes} +\usepackage{datatool,helvet,multirow,pgfplots,siunitx,xfrac,xtab} +\usepackage[capitalise]{cleveref} +\usepackage[final]{listings} +\usepackage[osf]{mathpazo} +\AtBeginDocument{\shorthandoff{<>}} +\crefformat{section}{#2Section~#1#3} +\Crefformat{section}{#2Section~#1#3} +\crefformat{subsection}{#2Section~#1#3} +\Crefformat{subsection}{#2Section~#1#3} +\crefformat{figure}{#2Figure~#1#3} +\Crefformat{figure}{#2Figure~#1#3} +\crefformat{table}{#2Table~#1#3} +\Crefformat{table}{#2Table~#1#3} +\crefrangeformat{table}{#3Tables~#1#4 to~#5#2#6} +\Crefrangeformat{table}{#3Tables~#1#4 to~#5#2#6} +\crefmultiformat{table}{#2Tables~#1#3}{ and~#2#1#3}{, #2#1#3}{, and~#2#1#3} +\Crefmultiformat{table}{#2Tables~#1#3}{ and~#2#1#3}{, #2#1#3}{, and~#2#1#3} +% Silence annoying fp package messages +\FPmessagesfalse +\pgfplotsset{compat = newest} +\sisetup{binary-units} +\DeclareSIUnit{\KWH}{kWh} +\DeclareSIPrePower\quartic{4} +\DeclareSIPostPower\tothefourth{4} +\DeclareSIQualifier\catalyst{cat} +\DeclareSIQualifier\isotropic{i} +\DeclareSIQualifier\polymer{pol} +\newlength\mylength +%\DisableImplementation +\begin{document} + \DocInput{\jobname.dtx} +\end{document} +% +% \fi +% +%\makeatletter +% +%^^A Some short cuts for the tables +%\NewDocumentCommand\DescribePrefix{m}{^^A +% \expandafter\SpecialUsageIndex\expandafter{\csname #1\endcsname}^^A +% #1 & \cs{#1} & \expandafter\si\expandafter{\csname #1\endcsname} +%} +%\NewDocumentCommand\DescribeUnit{m}{^^A +% \expandafter\SpecialUsageIndex\expandafter{\csname #1\endcsname}^^A +% #1 & +% \cs{#1} & +% \expandafter\si\expandafter{\csname #1\endcsname} +%} +%\NewDocumentCommand\DescribeNamedUnit{mm}{^^A +% \expandafter\SpecialUsageIndex\expandafter{\csname #2\endcsname}^^A +% #1 & +% \cs{#2} & +% \expandafter\si\expandafter{\csname #2\endcsname} +%} +% +%^^A For creating examples with nice highlighting of code, and so +%^^A on; based on the system used in the listings source (lstsample). +%\lst@RequireAspects{writefile} +%\newsavebox{\LaTeXdemo@box} +%\lstnewenvironment{LaTeXdemo}[1][code and example] +% {^^A +% \global\let\lst@intname\@empty +% \expandafter\let\expandafter\LaTeXdemo@end +% \csname LaTeXdemo@#1@end\endcsname +% \@nameuse{LaTeXdemo@#1}^^A +% } +% {\LaTeXdemo@end} +%\newcommand*\LaTeXdemo@new[3]{^^A +% \expandafter\newcommand\expandafter*\expandafter +% {\csname LaTeXdemo@#1\endcsname}{#2}^^A +% \expandafter\newcommand\expandafter*\expandafter +% {\csname LaTeXdemo@#1@end\endcsname}{#3}^^A +%} +%\newcommand*\LaTeXdemo@common{^^A +% \setkeys{lst} +% { +% basicstyle = \small\ttfamily, +% basewidth = 0.51em, +% gobble = 3, +% keywordstyle = \color{blue}, +% language = [LaTeX]{TeX}, +% moretexcs = +% { +% addto, +% ampere, +% ang, +% angstrom, +% becquerel, +% bel, +% bit, +% bottomrule, +% byte, +% cancel, +% candela, +% centi, +% color, +% coulomb, +% cubed, +% cubic, +% deci, +% decibel, +% degree, +% degreeCelsius, +% DeclareBinaryPrefix, +% DeclareRobustCommand, +% DeclareSIPostPower, +% DeclareSIPrefix, +% DeclareSIPrePower, +% DeclareSIQualifier, +% DeclareSIUnit, +% DTLdisplaydb, +% DTLforeach, +% DTLiffirstrow, +% DTLmul, +% DTLnewdb, +% DTLnewdbentry, +% DTLnewrow, +% farad, +% fontspec, +% gram, +% gray, +% henry, +% highlight, +% hour, +% Hz, +% joule, +% kelvin, +% kibi, +% kilo, +% kilogram, +% kWh, +% litre, +% lumen, +% lux, +% mathnormal, +% metre, +% mebi, +% micro, +% midrule, +% milli, +% mm, +% mole, +% multirow, +% num, +% numlist, +% numrange, +% of, +% pascal, +% per, +% percent, +% protected, +% radian, +% raiseto, +% robustify, +% rowcolor, +% second, +% selectlanguage, +% SendSettingsToPgf, +% si, +% SI, +% SIlist, +% SIrange, +% sievert, +% sisetup, +% SIUnitSymbolDegree, +% square, +% squared, +% tablenum, +% tesla, +% texorpdfstring, +% text, +% textmu, +% toprule, +% tothe, +% translate, +% unit, +% volt, +% watt +% } +% }^^A +%} +%\newcommand*\LaTeXdemo@input{^^A +% \MakePercentComment +% \catcode`\^^M=10\relax +% \small +% \begingroup +% \setkeys{lst} +% { +% SelectCharTable=\lst@ReplaceInput{\^\^I}{\lst@ProcessTabulator} +% }^^A +% \leavevmode +% \input{\jobname.tmp}^^A +% \endgroup +% \MakePercentIgnore +%} +%\LaTeXdemo@new{code and example} +% {^^A +% \setbox\LaTeXdemo@box=\hbox\bgroup +% \lst@BeginAlsoWriteFile{\jobname.tmp}^^A +% \LaTeXdemo@common +% } +% {^^A +% \lst@EndWriteFile +% \egroup +% \begin{center} +% \ifdim\wd\LaTeXdemo@box>0.48\linewidth\relax +% \hbox to\linewidth{\box\LaTeXdemo@box\hss}^^A +% \begin{minipage}{\linewidth} +% \LaTeXdemo@input +% \end{minipage} +% \else +% \begin{minipage}{0.48\linewidth} +% \LaTeXdemo@input +% \end{minipage} +% \hfill +% \begin{minipage}{0.48\linewidth} +% \hbox to\linewidth{\box\LaTeXdemo@box\hss}^^A +% \end{minipage} +% \fi +% \end{center} +% } +%\LaTeXdemo@new{code and float}{^^A +% \lst@BeginAlsoWriteFile{siunitx.tmp}^^A +% \LaTeXdemo@common +%}{^^A +% \lst@EndWriteFile +% \LaTeXdemo@input +%} +%\LaTeXdemo@new{code only} +% {\LaTeXdemo@common}{} +% +%^^A Turning of the marginpar warnings is a bit awkward. +%^^A It is achieved by temporarily disabling \@latex@warning@no@line +%\let\latex@addmarginpar\@addmarginpar +%\let\latex@warning@no@line\@latex@warning@no@line +%\def\@addmarginpar{^^A +% \let\@latex@warning@no@line\@gobble +% \latex@addmarginpar +% \let\@latex@warning@no@line\latex@warning@no@line +%} +% +%\ProvideDocumentCommand\opt{m}{\texttt{#1}} +% +%\makeatother +% +%\GetFileInfo{\jobname.sty} +% +%\title{^^A +% \textsf{siunitx} --- A comprehensive (SI) units package\thanks{^^A +% This file describes \fileversion, last revised \filedate.^^A +% }^^A +%} +%\author{^^A +% Joseph Wright\thanks +% {^^A +% E-mail: \href{mailto:joseph.wright@morningstar2.co.uk} +% {\texttt{joseph.wright@morningstar2.co.uk}}^^A +% }^^A +%} +%\date{Released \filedate} +% +%\maketitle +% +%\changes{v0.6}{2008/02/18}{First public testing release (as \pkg{si})} +%\changes{v1.0}{2008/06/15}{First official release} +%\changes{v1.1}{2008/09/28}{Package extended to a greater range of unit +% types} +%\changes{v1.2}{2009/01/22}{Correct handling for ranges of numbers +% added} +%\changes{v1.3}{2009/09/20}{Better definition for micro symbol} +%\changes{v1.4}{2010/01/16}{Detect entire document in non-serif font} +%\changes{v2.0}{2010/05/23}{Complete re-write of package to add many new +% features} +%\changes{v2.0c}{2010/06/07}{Mixed literal and macro units now print +% more reliably} +%\changes{v2.0d}{2010/06/10}{Fix error in \opt{table-format} option +% concerning exponent signs} +%\changes{v2.0e}{2010/06/20}{Correct behaviour of \cs{pm} in numbers +% when \texttt{abbreviations} configuration is loaded: problem +% introduced in v2.0c} +%\changes{v2.0f}{2010/06/27}{Fix issue with spacing of multiplication +% sign in text mode} +%\changes{v2.0g}{2010/06/28}{Fix issue with complex numbers in +% quotients} +%\changes{v2.0g}{2010/06/28}{Repair broken \opt{bracket-numbers} +% option} +%\changes{v2.0g}{2010/06/28}{Improve handling of complex root token} +%\changes{v2.0g}{2010/06/28}{Introduce localisation for text values} +%\changes{v2.0h}{2010/06/29}{Actually get localisation into the +% code} +%\changes{v2.0j}{2010/06/30}{Ensure symbols specified in +% \opt{input-symbols} are always printed in math mode} +%\changes{v2.0k}{2010/07/04}{Fix for \pkg{babel} French settings with +% \cs{fg} in tabular material} +%\changes{v2.0l}{2010/07/07}{Further adjustments to \pkg{babel} support} +%\changes{v2.0p}{2010/07/28}{Actually get change from v2.0o working} +%\changes{v2.0q}{2010/07/29}{Errors with free-standing unit code fixed} +%\changes{v2.0q}{2010/07/29}{Deal with bad definition of \cs{color} +% by \pkg{textpos} package} +%\changes{v2.0s}{2010/08/08}{Correct errors in rounding code when +% precision requested is zero decimal places} +%\changes{v2.0t}{2010/08/24}{Replace \cs{exp_afer:wN} in code for +% \cs{per} with \cs{exp_after:wN}} +%\changes{v2.0u}{2010/09/14}{Fix second possible issue with +% \pkg{textpos} package and \cs{color}} +%\changes{v2.0u}{2010/09/14}{Prevent infinite loop if \cs{SI} function +% is used with an empty number} +%\changes{v2.0v}{2010/09/26}{Internal changes reflecting \pkg{expl3} +% updates} +%\changes{v2.0w}{2010/09/29}{Deal with internal function used by +% REV\TeX{} in tables} +%\changes{v2.0x}{2010/10/05}{Fix bug when detecting single prefixes +% and converting prefixes to numbers} +%\changes{v2.1a}{2010/11/05}{Ensure that output of list separators is +% in text mode} +%\changes{v2.1a}{2010/11/05}{Print prefixes correctly in text mode +% when converting to numerical value} +%\changes{v2.1b}{2010/11/05}{Bug in printing code for complex part with +% no number fixed} +%\changes{v2.1b}{2010/11/05}{Bug in hyphen printing when detecting mode +% sorted} +%\changes{v2.1c}{2010/11/11}{Discourage line break between number and +% unit even when it is permitted} +%\changes{v2.1c}{2010/11/14}{After reviewing internals, \cs{numlist}, +% \cs{numrange}, \cs{SIlist} and \cs{SIrange} are documented as +% requiring text mode due to issues with spacing and line breaks} +%\changes{v2.1c}{2010/11/14}{Auto-detect math mode in tables and +% correct output accordingly} +%\changes{v2.1e}{2010/11/22}{Fix issues with text mode symbols and +% \pkg{fontspec} package} +%\changes{v2.1g}{2010/12/21}{Checks on the versions of \pkg{expl3} and +% \pkg{xparse} installed} +%\changes{v2.1h}{2011/01/18}{Detect AMS display-like environments} +%\changes{v2.1j}{2011/02/01}{Allow for loading of \pkg{inputenc} package +% with no options} +%\changes{v2.1k}{2011/02/09}{Bug fix when printing superscript minus +% signs and using \pkg{fontspec} package} +%\changes{v2.1m}{2011/03/18}{Avoid expansion of erroneous literal +% units when these are forbidden} +%\changes{v2.1m}{2011/03/20}{Ensure some output occurs in all cases +% when \opt{round-precision} is set to \opt{0} and \opt{round-mode} +% is set to \opt{places}} +%\changes{v2.1n}{2011/03/31}{Consistent behaviour for +% \opt{round-integer-to-decimal} when \opt{round-precision} is 0} +%\changes{v2.1o}{2011/04/03}{Fix incorrect font choice when +% \pkg{arev} package is loaded} +%\changes{v2.1o}{2011/04/03}{Account for negative exponents +% when using \opt{fixed-exponent} system} +%\changes{v2.1p}{2011/04/04}{Bad table alignment when some rows +% contain comparators fixed} +%\changes{v2.1p}{2011/04/04}{Poor position of comparators in +% numbers fixed} +%\changes{v2.2a}{2011/04/15}{Fix issue with \texttt{*} tokens in +% tabular preambles} +%\changes{v2.2a}{2011/04/15}{Expand macros with arguments correctly +% in tables} +%\changes{v2.2a}{2011/04/16}{Group digits for input containing symbolic +% entries} +%\changes{v2.2a}{2011/04/16}{Insert tokens correctly when last tabular cell +% does not end \texttt{\textbackslash\textbackslash}} +%\changes{v2.2a}{2011/04/16}{Fix bug with literal units and auto-insertion +% of \num{1} when \opt{per-mode} is \opt{symbol}} +%\changes{v2.2b}{2011/04/17}{Make \cs{of} work in hyper-linked sections} +%\changes{v2.2b}{2011/04/17}{Fix bug with \cs{highlight} macro when +% no colour support is loaded} +%\changes{v2.2b}{2011/04/19}{Fix bad formatting of negative exponents when +% using the \opt{output-exponent-marker} option} +%\changes{v2.2c}{2011/04/20}{Fix bad interaction with \pkg{cellspace} package} +%\changes{v2.2d}{2011/04/28}{Fix the \opt{strict} option} +%\changes{v2.2e}{2011/05/23}{Fix incorrect interpretation of complex numbers +% with no real part} +%\changes{v2.2g}{2011/06/02}{Correctly space \cs{degree} and similar units +% in lists and ranges when only a single unit is given} +%\changes{v2.2h}{2011/06/03}{Fix bug in significant figures rounding code +% for some integer part values} +%\changes{v2.2i}{2011/06/15}{Fix \opt{detect-mode} option inside +% table cells} +%\changes{v2.2j}{2011/06/26}{Fix incorrect line breaking in \cs{SIrange}} +%\changes{v2.2k}{2011/06/27}{Fix behaviour of subscripts inside alignments +% when printing in text mode} +%\changes{v2.2l}{2011/06/30}{Fix loss of main unit when \opt{per-mode} is set +% to \opt{symbol} and a pre-unit is used} +%\changes{v2.3}{2011/06/19}{New implementation for alignment in \texttt{S} +% column} +%\changes{v2.3a}{2011/07/09}{Restore fix in v2.2l missing in v2.3} +%\changes{v2.3b}{2011/08/08}{Adjust internal load order so that +% \opt{free-standing-units} works correctly for abbreviations} +%\changes{v2.3c}{2011/07/12}{Fix display of \( \pm \) in numbers when +% \opt{separate-uncertainty} is \opt{true} and literal units are used} +%\changes{v2.3d}{2011/08/18}{Fix broken superscript display in literal unit +% mode} +%\changes{v2.3e}{2011/09/09}{Internal changes to work with \LaTeX3 +% updates} +%\changes{v2.3f}{2011/09/03}{Fix processing of numbers in tables when entire +% number is invalid} +%\changes{v2.3g}{2011/10/06}{Deal with erroneous leading zero in some +% fixed exponent cases} +%\changes{v2.3h}{2011/10/14}{Ensure math mode for exponent products in all +% circumstances} +%\changes{v2.3h}{2011/10/14}{Improvements to output when using \pkg{tex4ht}} +%\changes{v2.4}{2011/11/03}{Reduce number of math mode options, improving +% consistency of output} +%\changes{v2.4a}{2011/11/28}{Extend search-and-replace code for UTF-8 +% characters} +%\changes{v2.4a}{2011/12/04}{Use a more cautious approach to changing +% settings at the start of the document} +%\changes{v2.4b}{2011/12/06}{Erroneous doubled \texttt{\#} corrected} +%\changes{v2.4c}{2011/12/09}{Erroneous check for text mode sanserif font fixed} +%\changes{v2.4d}{2011/12/09}{Fix for edge-case user commands in captions +% where the command clashes with a unit name} +%\changes{v2.4e}{2011/12/11}{Fix issue with \pkg{inputenc} package and +% some of the recent special symbol changes} +%\changes{v2.4f}{2011/12/21}{Allow easier use of headings when not parsing +% numbers in tables} +%\changes{v2.4f}{2011/12/23}{Fix bug with detection of bold font in table +% cells} +%\changes{v2.4g}{2012/01/06}{Update internals to match changes in \pkg{expl3} +% which caused issues with some tokens in numerical arguments} +%\changes{v2.4h}{2012/01/15}{Bug fix for implementation of +% \opt{reciprocal-positive-first}} +%\changes{v2.4i}{2012/01/19}{Bug fix for rounding with large numbers of +% decimal places} +%\changes{v2.4j}{2012/01/26}{Leave vertical mode before any document-level +% commands} +%\changes{v2.4k}{2012/03/22}{Internal changes to allow for \pkg{breqn} +% package tricks} +%\changes{v2.4l}{2012/03/23}{Fix a load-order issue with \pkg{soulpos} +% package} +%\changes{v2.4m}{2012/04/03}{Correct bug in \cs{SIlist} when only a single +% number is given} +%\changes{v2.4n}{2012/04/04}{Allow conversion of numbers with more than +% nine digits to scientific notation} +% \changes{v2.5}{2012/04/07}{Fixed table code to give fewer underfull +% boxes when comparators are used} +% \changes{v2.5}{2015/04/07}{Added \opt{zero-decimal-to-integer} option} +% \changes{v2.5}{2012/04/07}{Added \opt{omit-uncertainty} option} +% \changes{v2.5}{2012/04/08}{Modified \opt{fixed-exponent} such that it can +% remove an exponent part} +% \changes{v2.5}{2012/04/08}{Modified number of intrinsically-mathematical +% options} +% \changes{v2.5a}{2012/04/19}{Fixed support for \enquote{dynamic} nature of spacing +% in free standing units (bug introduced in v2.5)} +% \changes{v2.5b}{2012/04/20}{Fixed treatement \texttt{\^} and \texttt{\_} +% in literal units when \pkg{breqn} package is loaded} +% \changes{v2.5b}{2012/04/20}{Added support for \pkg{eulervm} package} +% \changes{v2.5c}{2012/04/03}{Fixed conversion of numbers with more than +% nine digits when using fixed exponents} +% \changes{v2.5c}{2012/05/03}{Modified treatment entirely empty cells in +% \texttt{s} columns} +% \changes{v2.5d}{2012/06/11}{Extend range of settings automatically altered +% to use UTF-8 values is appropriate} +% \changes{v2.5d}{2012/06/11}{Added \opt{qualifier-phrase} option} +% \changes{v2.5d}{2012/06/11}{Added \opt{phrase} choice for \opt{qualifier-mode} +% option} +% \changes{v2.5e}{2012/06/13}{Fixed an internal error in unit expansion +% introduced in v2.4f} +% \changes{v2.5f}{2012/07/16}{Modified internals to track \pkg{expl3} changes} +% \changes{v2.5g}{2012/07/22}{Fixed \opt{binary-units} option} +% \changes{v2.5h}{2012/08/28}{Modified literal unit test to allow spaces in +% units to be ignored} +% \changes{v2.5i}{2012/09/11}{Fixed alignment of values without uncertainties in +% columns where space is reserved for uncertainties} +% \changes{v2.5j}{2012/09/18}{Fixed rounding when uncertainties are present} +% \changes{v2.5k}{2012/09/20}{Fixed a warning with \pkg{amsmath} related to fraction +% functions} +% \changes{v2.5k}{2012/11/13}{Fixed handling spaces correctly after start of document} +% \changes{v2.5l}{2012/11/21}{Modified internals to track \pkg{expl3} changes} +% \changes{v2.5m}{2012/11/27}{Fixed bug with UTF-8 engines and literal units} +% \changes{v2.5m}{2012/11/27}{Fixed \cs{highlight} behavior in bookmarks} +% \changes{v2.5m}{2012/11/27}{Modified loading of \opt{binary-units}} +% \changes{v2.5m}{2012/11/27}{Fixed right-to-left mode with \pkg{bidi} +% package} +% \changes{v2.5n}{2012/12/29}{Fixed transmission of grouping information by +% \cs{SendSettingsToPgf}} +% \changes{v2.5o}{2013/01/09}{Modified internals to track \pkg{expl3} changes} +% \changes{v2.5p}{2013/02/01}{Fixed printing of \cs{pm} and \cs{mp} when used +% as signs in text mode} +% \changes{v2.5q}{2013/03/10}{Fixed use active \texttt{-} in numbersn} +% \changes{v2.5q}{2013/03/10}{Fixed binary units in tables} +% \changes{v2.5r}{2013/07/11}{Modified internals to track \pkg{expl3} changes} +% \changes{v2.5s}{2013/07/31}{Modified internals to track \pkg{expl3} changes} +% \changes{v2.6}{2013/11/19}{Fixed loading when \pkg{mdwtab} is in use} +% \changes{v2.6}{2014/09/03}{Fixed minus sign when \pkg{tex4ht} is in use} +% \changes{v2.6}{2014/09/03}{Fixed spacing when printing comparators} +% \changes{v2.6}{2014/09/03}{Modified treatment of hard spaces (\texttt{\~}) in +% argument of \cs{num}} +% \changes{v2.6}{2014/09/03}{Modified standard setting for \opt{mode} option +% to \opt{math}} +% \changes{v2.6}{2014/09/04}{Fixed printing of uncertainties when the +% input is an integer and the uncertainty is given as a separate part} +% \changes{v2.6}{2014/09/04}{Fixed definition \cs{fg} in +% bookmarks when \pkg{babel} is loaded with the \opt{french} option} +% \changes{v2.6}{2014/09/05}{Fixed printing exponent in tables when +% \opt{output-exponent-marker} is active} +% \changes{v2.6a}{2014/09/15}{Modified glyph selection when \pkg{fontspec} +% is detected} +% \changes{v2.6b}{2014/09/27}{Modified range of font shapes which can be +% detected} +% \changes{v2.6c}{2014/10/01}{Fixed use of \cs{micro} when \pkg{fontspec} +% is loaded but \pkg{unicode-math} is not} +% \changes{v2.6d}{2014/10/07}{Fixed conversion of \enquote{long} to +% \enquote{short} uncertainty values with integer mantissas} +% \changes{v2.6e}{2015/01/21}{Modified symbol selection where \pkg{fontspec} +% and certain other packages are in use} +% \changes{v2.6f}{2015/04/01}{Fixed \opt{table-sign-exponent} and +% \opt{table-sign-mantissa} options when set \opt{false}} +% \changes{v2.6f}{2015/04/04}{Modified detection of \pkg{mathspec}} +% \changes{v2.6g}{2015/06/24}{Fixed issue with empty table cells} +% \changes{v2.6h}{2015/07/17}{Modified internals to track \pkg{expl3} changes} +% \changes{v2.6i}{2015/08/18}{Fixed rounding of numbers with large numbers of +% digits} +% \changes{v2.6i}{2015/08/18}{Fixed behaviour of \cs{cancel} when printing +% in math mode} +% \changes{v2.6j}{2015/09/01}{Fixed printing of all units when +% \opt{exponent-to-prefix} is set} +% \changes{v2.6j}{2015/09/01}{Fixed appearance of $\pm$ when +% \opt{exponent-to-prefix} is set} +% \changes{v2.6k}{2015/09/12}{Modified internals to track \pkg{expl3} changes} +% \changes{v2.6l}{2015/09/14}{Fixed an internal error} +% \changes{v2.6m}{2015/10/15}{Fixed an issue with \pkg{mwtab}} +% \changes{v2.6n}{2015/12/31}{Modified definition for degree Celsius} +% \changes{v2.6n}{2015/12/31}{Fixed {\aa}ngstr{\"o}m symbol with \LuaTeX{}} +% \changes{v2.6o}{2016/01/05}{Added support for unit powers when converting exponents +% to prefixes} +% \changes{v2.6p}{2016/01/13}{Added support for reciprocal powers when converting +% exponents to prefixes} +% \changes{v2.6p}{2016/01/19}{Modified definition for degree Celsius} +% \changes{v2.6q}{2016/03/01}{Fixed font selection when document commands are +% used inside table cells in \texttt{S} columns} +% \changes{v2.6r}{2016/06/06}{Fixed color safety issue} +% \changes{v2.6r}{2016/08/14}{Fixed internal \pkg{expl3} usage issues} +% \changes{v2.6r}{2016/08/21}{Fixed handling \texttt{e0}} +% \changes{v2.6r}{2016/08/21}{Added a warning when color support is not available} +% \changes{v2.6s}{2016/09/02}{Removed one excess warning} +% \changes{v2.7}{2016/11/11}{Added first documented code level interfaces} +% \changes{v2.7}{2016/11/23}{Fixed behavior when \pkg{cellspace} is applied to +% math mode material} +% \changes{v2.7b}{2017/01/28}{Fixed large numbers in scientific mode} +% \changes{v2.7c}{2017/02/01}{Fixed spacing of integers in tables when +% aligning decimal marker to center} +% \changes{v2.7d}{2017/02/19}{Fixed doubled pre-number tokens in tables} +% \changes{v2.7e}{2017/03/06}{Modified treatment of \texttt{+} } +% \changes{v2.7f}{2017/03/23}{Fixed spacing with \opt{reciprocal-positive-first} +% setting} +% \changes{v2.7g}{2017/05/19}{Fixed an issue with recent \pkg{expl3} update} +% \changes{v2.7h}{2017/06/12}{Modified code internals} +% \changes{v2.7i}{2017/07/23}{Fixed an incorrect variable name} +% \changes{v2.7k}{2017/11/01}{Fixed formatting of units when not parsed} +% \changes{v2.7l}{2018/03/11}{Modified \pkg{unicode-math} support} +% \changes{v2.7m}{2018/03/20}{Modified definition of \cs{astronomicalunit} unit} +% \changes{v2.7n}{2018/04/27}{Fixed symbolic input and digit grouping} +% \changes{v2.7q}{2018/05/11}{Fixed patching of \pkg{cellspace} columns} +% \changes{v2.7r}{2018/05/16}{Fixed issue in tabulars when REV\TeX{} is in use} +% \changes{v2.7s}{2018/05/17}{Modified package date format} +% +%\begin{abstract} +% Physical quantities have both numbers and units, and each physical +% quantity should be expressed as the product of a number and a unit. +% Typesetting physical quantities requires care to ensure that the +% combined mathematical meaning of the number--unit combination is +% clear. In particular, the SI units system lays down a consistent +% set of units with rules on how these are to be used. However, +% different countries and publishers have differing conventions on +% the exact appearance of numbers (and units). +% +% The \pkg{siunitx} package provides a set of tools for authors +% to typeset quantities in a consistent way. The package has an +% extended set of configuration options which make it possible to +% follow varying typographic conventions with the same input syntax. +% The package includes automated processing of numbers and units, and +% the ability to control tabular alignment of numbers. +%\end{abstract} +% +%\tableofcontents +% +%\begin{documentation} +% +%\section{Introduction} +% +% The correct application of units of measurement is very important +% in technical applications. For this reason, carefully-crafted +% definitions of a coherent units system have been laid down by the +% \emph{Conf\'erence G\'en\'erale des Poids et +% Mesures} (CGPM): this has resulted in the \emph{Syst\`eme +% International d'Unit\'es} (SI). At the same time, typographic +% conventions for correctly displaying both numbers and units exist to +% ensure that no loss of meaning occurs in printed matter. +% +% \pkg{siunitx} aims to provide a unified method for \LaTeX{} users to +% typeset numbers and units correctly and easily. The design +% philosophy of \pkg{siunitx} is to follow the agreed rules by +% default, but to allow variation through option settings. In this way, +% users can use \pkg{siunitx} to follow the requirements of +% publishers, co-authors, universities, \emph{etc}.~without needing to +% alter the input at all. +% +%\section{Installation} +% +% The package is supplied in \file{dtx} format and as a pre-extracted +% zip file, \file{\jobname.tds.zip}. The later is most convenient for +% most users: simply unzip this in your local texmf directory and +% run \texttt{texhash} to update the database of file locations. If +% you want to unpack the \file{dtx} yourself, running +% \texttt{tex \jobname.dtx} will extract the package whereas +% \texttt{latex \jobname.dtx} will extract it and also typeset the +% documentation. +% +% The package requires \LaTeX3 support as provided in the +% \pkg{l3kernel} and \pkg{l3packages} bundles. Both of these are available +% on \href{http://www.ctan.org}{\textsc{ctan}} as ready-to-install +% zip files. Suitable versions are available in MiK\TeX{}~2.9 and +% \TeX{}~Live 2015 (updating the relevant packages online may be +% necessary). \LaTeX3, and so \pkg{siunitx}, requires the \eTeX{} +% extensions: these are available on all modern \TeX{} systems. +% +% Typesetting the documentation requires a number of packages in +% addition to those needed to use the package. This is mainly +% because of the number of demonstration items included in the text. To +% compile the documentation without error, you will need the packages: +%\begin{itemize} +% \item \pkg{amsmath} +% \item \pkg{booktabs} +% \item \pkg{cancel} +% \item \pkg{caption} +% \item \pkg{cleveref} +% \item \pkg{colortbl} +% \item \pkg{csquotes} +% \item \pkg{helvet} +% \item \pkg{mathpazo} +% \item \pkg{multirow} +% \item \pkg{listings} +% \item \pkg{pgfplots} +% \item \pkg{xcolor} +%\end{itemize} +% +%\section{\pkg{siunitx} for the impatient} +% +% The package provides the user macros: +%\begin{itemize} +% \item \cs{ang}\oarg{options}\marg{angle} +% \item \cs{num}\oarg{options}\marg{number} +% \item \cs{si}\oarg{options}\marg{unit} +% \item \cs{SI}\oarg{options}\marg{number}\oarg{pre-unit}\marg{unit} +% \item \cs{numlist}\oarg{options}\marg{numbers} +% \item \cs{numrange}\oarg{options}\marg{numbers}\marg{number2} +% \item \cs{SIlist}\oarg{options}\marg{numbers}\marg{unit} +% \item \cs{SIrange}\oarg{options}\marg{number1}\marg{number2}^^A +% \marg{unit} +% \item \cs{sisetup}\marg{options} +% \item \cs{tablenum}\oarg{options}\marg{number} +%\end{itemize} +% plus the \texttt{S} and \texttt{s} column types for decimal +% alignments and units in tabular environments. These user macros and +% column types are designed for +% typesetting numbers and units with control of appearance and with +% intelligent processing. +% +% Numbers are processed with understanding of exponents, complex numbers +% and multiplication. +%\begin{LaTeXdemo} +% \num{12345,67890} \\ +% \num{1+-2i} \\ +% \num{.3e45} \\ +% \num{1.654 x 2.34 x 3.430} +%\end{LaTeXdemo} +% +% The unit system can interpret units given as text to be used directly +% or as macro-based units. In the latter case, different formatting is +% possible. +%\begin{LaTeXdemo} +% \si{kg.m.s^{-1}} \\ +% \si{\kilogram\metre\per\second} \\ +% \si[per-mode=symbol] +% {\kilogram\metre\per\second} \\ +% \si[per-mode=symbol] +% {\kilogram\metre\per\ampere\per\second} +%\end{LaTeXdemo} +% +% Simple lists and ranges of numbers can be handled. +%\begin{LaTeXdemo} +% \numlist{10;20;30} \\ +% \SIlist{0.13;0.67;0.80}{\milli\metre} \\ +% \numrange{10}{20} \\ +% \SIrange{0.13}{0.67}{\milli\metre} +%\end{LaTeXdemo} +% +% By default, all text is typeset in the current upright math +% font. This can be changed by setting the appropriate options: +% "\sisetup{detect-all}" will use the current font for typesetting. +% +%\section{Using the \pkg{siunitx} package} +% +%\subsection{Loading the package} +% +% The package should be loaded in the usual \LaTeXe{} way. +%\begin{LaTeXdemo}[code only] +% \usepackage{siunitx} +%\end{LaTeXdemo} +% The key--value options described later in this document can be used +% when loading the package, for example +%\begin{LaTeXdemo}[code only] +% \usepackage[version-1-compatibility]{siunitx} +%\end{LaTeXdemo} +% to use options from version 1 of the package. +% +%\subsection{Numbers} +% +%\DescribeMacro{\num} +%\begin{syntax} +% \cs{num}\oarg{options}\marg{number} +%\end{syntax} +% Numbers are automatically formatted by the \cs{num} macro. This +% takes one optional argument, \meta{options}, and one mandatory one, +% \meta{number}. The contents of \meta{number} are automatically +% formatted. The formatter removes 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} +% The \opt{mode} option determines whether \pkg{siunitx} uses +% math or text mode when printing output. The choices are \opt{math} and +% \opt{text}. When using math mode, text is printed using a math font +% whereas in text mode a text font is used. The extent to which this is +% visually obvious depends on the fonts in use in the document. This +% manual uses old style (lower-case) figures in text mode to highlight +% the differences. This option has no effect if the \opt{detect-mode} +% switch is \opt{true}. +% +%\DescribeOption{math-rm} +%\DescribeOption{math-sf} +%\DescribeOption{math-tt} +%\DescribeOption{text-rm} +%\DescribeOption{text-sf} +%\DescribeOption{text-tt} +% If font family detection is inactive, \pkg{siunitx} uses the font +% family stored in either \opt{math-rm} or \opt{text-rm} for +% output. The choice of \opt{math} or \opt{text} depends on the +% \opt{mode} setting. If font family detection is active, +% \pkg{siunitx} may be using a sans serif or monospaced font for +% output. In math mode, these are stored in \opt{math-sf} and +% \opt{math-tt}, and for text mode in \opt{text-sf} and \opt{text-tt}. +% Notice that the detected and output font families can differ. +%\begin{LaTeXdemo} +% \sisetup{detect-family}% +% \num{1234} \\ +% { \sffamily \num{1234} } \\ +% \SI{99}{\metre} \\ +% \sisetup{math-rm = \mathtt}% +% \SI{99}{\metre} +%\end{LaTeXdemo} +% +%\DescribeOption{color} +% The colour of printed output can be set using the \opt{color} +% option. When no colour is given, printing follows the surrounding +% text. In contrast, when a specific colour is given, it is used +% irrespective of the surroundings. As there are a number of different +% colour models available, it is left to user to load \pkg{color} or +% a more powerful colour package such as \pkg{xcolor}. +%\begin{LaTeXdemo} +% \color{red} +% Some text \\ +% \SI{4}{\metre\per\sievert} \\ +% More text \\ +% \SI[color = blue]{4}{\metre\per\sievert} \\ +% Still red here! +%\end{LaTeXdemo} +% +% Every one of the font options can be given independently for units +% and number, with the prefixes \opt{unit-} and \opt{number-}, +% respectively. This allows fine control of output. +%\begin{LaTeXdemo} +% \SI{4}{\angstrom} \\ +% \SI[number-color = green]{4}{\angstrom} \\ +% \SI[unit-color = green]{4}{\angstrom} +%\end{LaTeXdemo} +% +%\subsection{Parsing numbers} +% +% The package uses a sophisticated parsing system to understand +% numbers. This allows \pkg{siunitx} to carry out a range of +% formatting, as described later. All of the input options take lists of +% literal tokens, and are summarised in \cref{tab:opt:num:in}. +% +%\begin{table} +% \centering +% \caption{Options for number parsing.} +% \label{tab:opt:num:in} +% \begin{tabular}{>{\ttfamily}ll>{\ttfamily}l} +% \toprule +% \multicolumn{1}{l}{Option name} & +% Type & +% \multicolumn{1}{l}{Default} \\ +% \midrule ^^A ( +% input-close-uncertainty & Literal & ) \\ +% input-comparators & Literal & +% <=>\cs{approx}\cs{ge}\cs{geq} \\ +% & & \cs{gg}\cs{le}\cs{leq}\cs{ll} \cs{sim} \\ +% input-complex-roots & Literal & ij \\ +% input-decimal-markers & Literal & ., \\ +% input-digits & Literal & 0123456789 \\ +% input-exponent-markers & Literal & dDeE \\ +% input-ignore & Literal & \meta{none} \\ +% input-open-uncertainty & Literal & ( \\ ^^A ) +% input-protect-tokens & Literal & +% \cs{approx}\cs{dots}\cs{ge}\cs{geq}\cs{gg}\cs{le} \\ +% & & \cs{leq}\cs{ll}\cs{mp}\cs{pi}\cs{pm}\cs{sim} \\ +% input-signs & Literal & +-\cs{pm}\cs{mp} \\ +% input-uncertainty-signs & Literal & \cs{pm} \\ +% input-symbols & Literal & \cs{pi}\cs{dots} \\ +% parse-numbers & Switch & true \\ +% \bottomrule +% \end{tabular} +%\end{table} +% +%\DescribeOption{input-digits} +%\DescribeOption{input-decimal-markers} +%\DescribeOption{input-signs} +%\DescribeOption{input-exponent-markers} +% The basic parts of a number are the digits, any sign and a separator +% between the integer and decimal parts. These are stored in the input +% options \opt{input-digits}, \opt{input-decimal-markers} and +% \opt{input-signs}, respectively. More than one input decimal marker +% can be used: it will be converted by the package to the appropriate +% output marker. Numbers which include an exponent part also require +% a marker for the exponent: this again is taken from the range of +% tokens in the \opt{input-exponent-markers} option. +% +%\DescribeOption{input-symbols} +%\DescribeOption{input-ignore} +% As well as \enquote{normal} digits, the package will interpret +% symbolic \enquote{numbers} (such as \cs{pi}) correctly if they are +% included in the \opt{input-symbols} list. Symbols are always +% printed in math mode. Tokens given in the \opt{input-ignore} list +% are totally passed over by \pkg{siunitx}: they will be removed from +% the input with no further processing. +% +%\DescribeOption{input-comparators} +%\changes{v2.1}{2010/10/26}{New \opt{input-comparators} option +% for numbers greater than, less than and so on} +% In addition to signs, \pkg{siunitx} can recognise comparators, such +% as \texttt{<}. The package will automatically carry out conversions +% for "<<", ">>", "<=" and ">=" to \cs{ll}, \cs{gg}, \cs{le} and +% \cs{ge}, respectively: +%\begin{LaTeXdemo} +% \num{< 10} \\ +% \SI{>> 5}{\metre} \\ +% \num{\le 0.12} +%\end{LaTeXdemo} +% +%\DescribeOption{input-open-uncertainty} +%\DescribeOption{input-close-uncertainty} +% In some fields, it is common to give the uncertainty in a number +% in brackets after the main part of the number, for example +% \enquote{\num{1.234(5)}}. The opening and closing symbols used for +% this type of input are set as \opt{input-open-uncertainty} and +% \opt{input-close-uncertainty}. +%\DescribeOption{input-uncertainty-signs} +%\changes{v2.2}{2011/04/03}{New \opt{input-uncertainty-signs} +% option} +% Alternatively, the uncertainty may be given as a separate part +% following a sign. Which signs are valid for this operation is +% determined by the \opt{input-uncertainty-signs} option. As with +% other signs, the combination \texttt{+-} will automatically be +% converted to \cs{pm} internally. +%\begin{LaTeXdemo} +% \num{9.99(9)} \\ +% \num{9.99 +- 0.09} \\ +% \num{9.99 \pm 0.09} \\ +% \num{123 +- 4.5} \\ +% \num{12.3 +- 6} +%\end{LaTeXdemo} +% +%\DescribeOption{input-complex-roots} +% When using complex numbers in input, the complex root +% \( ( \mathrm{i} = \sqrt{-1} \, ) \) is indicated by one of the tokens stored +% in \opt{input-complex-roots}. The parser understands complex root +% symbols given either before or after the associated number (but will +% detect any invalid arrangement): +%\begin{LaTeXdemo} +% \num{9.99 + 88.8i} \\ +% \num{9.99 + i88.8} +%\end{LaTeXdemo} +% +%\DescribeOption{input-protect-tokens} +% Some symbols can be problematic under expansion in \LaTeXe. To allow +% these to be used in input without issue, the package can protect these +% tokens while expanding input. Symbols to be protected in this way +% should be listed in \opt{input-protect-tokens}. +% +%\DescribeOption{parse-numbers} +% The \opt{parse-numbers} option turns the entire parsing system on +% and off. The option is made available for two reasons. First, if +% all of the numbers in a document are to be reproduced \enquote{as +% given}, turning off the parser will represent a significant saving in +% processing required. Second, it allows the use of arbitrary \TeX{} +% code in numbers. If the parser is turned off, the input will be +% printed in math mode (requiring \cs{text} to protect any text +% in the number). +%\begin{LaTeXdemo} +% \num[parse-numbers = false]{\sqrt{2}} \\ +% \SI[parse-numbers = false]{\sqrt{3}}{\metre} +%\end{LaTeXdemo} +% +%\subsection{Post-processing numbers} +% +% Before typesetting numbers, various post-processing steps can be +% carried out. These involve adding or removing information from the +% number in a systematic way; the options are summarised in +% \cref{tab:opt:num:post}. +% +%\begin{table} +% \centering +% \caption{Number post-processing options.} +% \label{tab:opt:num:post} +% \begin{tabular}{>{\ttfamily}ll>{\ttfamily}l} +% \toprule +% \multicolumn{1}{l}{Option name} & +% Type & +% \multicolumn{1}{l}{Default} \\ +% \midrule +% add-decimal-zero & Switch & true \\ +% add-integer-zero & Switch & true \\ +% explicit-sign & Literal & \meta{none} \\ +% fixed-exponent & Integer & 0 \\ +% minimum-integer-digits & Integer & 0 \\ +% omit-uncertainty & Switch & false \\ +% retain-explicit-plus & Switch & false \\ +% retain-unity-mantissa & Switch & true \\ +% retain-zero-exponent & Switch & false \\ +% round-half & Choice & up \\ +% round-integer-to-decimal & Switch & false \\ +% round-minimum & Literal & 0 \\ +% round-mode & Choice & off \\ +% round-precision & Integer & 2 \\ +% scientific-notation & Switch & false \\ +% zero-decimal-to-integer & Switch & false \\ +% \bottomrule +% \end{tabular} +%\end{table} +% +%\DescribeOption{round-mode} +%\DescribeOption{round-precision} +%\changes{v2.1n}{2011/03/31}{Set output to 0 when \opt{round-mode} +% is \opt{figures} and \opt{round-precision} is 0} +% The \pkg{siunitx} package can round numerical input to a fixed +% number of significant figures or decimal places. This is controlled by +% the \opt{round-mode} option, which takes the choices \opt{off}, +% \opt{figures} and \opt{places}. When rounding is turned on, the +% number of digits used (either decimal places or significant figures in +% the mantissa) is set using the \opt{round-precision} option. No rounding will +% take place if the number contains an uncertainty component. +%\begin{LaTeXdemo} +% \num{1.23456} \\ +% \num{14.23} \\ +% \num{0.12345(9)} \\ +% \sisetup{ +% round-mode = places, +% round-precision = 3 +% }% +% \num{1.23456} \\ +% \num{14.23} \\ +% \num{0.12345(9)} \\ +% \sisetup{ +% round-mode = figures, +% round-precision = 3 +% }% +% \num{1.23456} \\ +% \num{14.23} \\ +% \num{0.12345(9)} +%\end{LaTeXdemo} +%\DescribeOption{round-integer-to-decimal} +%\changes{v2.1}{2010/10/25}{New \opt{zero-integer-to-decimal} option +% to convert integers to decimals on rounding} +% The standard settings for \pkg{siunitx} do not add a decimal part +% if none was given in the input. The \opt{round-integer-to-decimal} +% option can be used to allow this conversion as part of the rounding +% process. +%\begin{LaTeXdemo} +% \num[round-mode = figures]{1} \\ +% \num[round-mode = places]{1} \\ +% \sisetup{round-integer-to-decimal} +% \num[round-mode = figures]{1} \\ +% \num[round-mode = places]{1} +%\end{LaTeXdemo} +% \DescribeOption{zero-decimal-to-integer} +% It may be desirable to convert decimals to integers if the decimal part is +% zero. This is set up using the \opt{zero-decimal-to-integer} option. +%\begin{LaTeXdemo} +% \num{2.0} \\ +% \num{2.1} \\ +% \sisetup{zero-decimal-to-integer} +% \num{2.0} \\ +% \num{2.1} +%\end{LaTeXdemo} +%\DescribeOption{round-minimum} +%\changes{v2.1}{2010/10/27}{New \opt{round-minimum} option +% to set a floor for rounding numbers downward} +% There are cases in which rounding will result in the number reaching +% zero. It may be desirable to show such results as below a threshold +% value. This can be achieved by setting \opt{round-minimum} to the +% threshold value. There will be no effect when rounding to a number of +% significant figures as it is not possible to obtain the value zero in +% these cases. +%\begin{LaTeXdemo} +% \sisetup{round-mode = places}% +% \num{0.0055} \\ +% \num{0.0045} \\ +% \sisetup{round-minimum = 0.01}% +% \num{0.0055} \\ +% \num{0.0045} +%\end{LaTeXdemo} +% \DescribeOption{round-half} +% \changes{v2.4}{2011/1/04}{New \opt{round-half} option} +% In cases where the rounded part of a number is exactly half, there are +% two common methods for \enquote{breaking the tie}. The choice of method +% is determined by the option \opt{round-half}, which recognises the +% choices \opt{up} and \opt{even}. +%\begin{LaTeXdemo} +% \sisetup{round-mode = places, round-half = up}% +% \num{0.055} \\ +% \num{0.045} \\ +% \sisetup{round-half = even}% +% \num{0.055} \\ +% \num{0.045} +%\end{LaTeXdemo} +% +%\DescribeOption{add-decimal-zero} +%\DescribeOption{add-integer-zero} +% It is possible to give real (floating point) numbers as input omitting +% the decimal or the integer parts of the number (for example \num{.123} +% or \num{123.}). The options \opt{add-decimal-zero} and +% \opt{add-integer-zero} allow the package to \enquote{fill in} the +% missing zero. +%\begin{LaTeXdemo} +% \num{123.} \\ +% \num{456} \\ +% \num{.789} \\ +% \sisetup{ +% add-decimal-zero = false, +% add-integer-zero = false, +% }% +% \num{123.} \\ +% \num{456} \\ +% \num{.789} +%\end{LaTeXdemo} +%\DescribeOption{minimum-integer-digits} +%\changes{v2.2}{2011/04/04}{New \opt{minimum-integer-digits} option} +% Related is the \opt{minimum-integer-digits} option. This applies +% only to the integer part of the mantissa, and ensures that it will +% contain at least the specified number of digits. This is achieved +% by padding with zeros if needed. +%\begin{LaTeXdemo} +% \num{123} \\ +% \num[minimum-integer-digits = 1]{123} \\ +% \num[minimum-integer-digits = 2]{123} \\ +% \num[minimum-integer-digits = 3]{123} \\ +% \num[minimum-integer-digits = 4]{123} +%\end{LaTeXdemo} +% +%\DescribeOption{explicit-sign} +%\DescribeOption{retain-explicit-plus} +% The inclusion of a leading plus sign is usually unnecessary for +% positive numbers, and so the \opt{retain-explicit-plus} option is +% available to control whether these are printed. At the same time, it +% may be useful to force all numbers to have a sign. This behaviour +% is controlled by the \opt{explicit-sign} option: this is used if +% given and if no sign was present in the input. +%\begin{LaTeXdemo} +% \num{+345} \\ +% \num[retain-explicit-plus]{+345} \\ +% \num[explicit-sign = -]{345} \\ +% \num[explicit-sign = -]{+345} +%\end{LaTeXdemo} +% +%\DescribeOption{retain-unity-mantissa} +%\DescribeOption{retain-zero-exponent} +% The retention of a zero exponent is controlled by the +% \opt{retain-zero-exponent} option. The retention of a mantissa of one +% is likewise controlled by the \opt{retain-unity-mantissa} option. +%\begin{LaTeXdemo} +% \num{1e4} \\ +% \num[retain-unity-mantissa = false]{1e4} \\ +% \num{444e0} \\ +% \num[retain-zero-exponent = true]{444e0} +%\end{LaTeXdemo} +% +%\DescribeOption{scientific-notation} +%\changes{v2.1}{2010/10/13}{New \opt{scientific-notation} option +% for to use exponent form for numbers in all cases} +%\changes{v2.2}{2011/04/04}{Extend \opt{scientific-notation} option +% to include \opt{engineering} mode} +%\DescribeOption{fixed-exponent} +% Numbers can be converted to scientific notation by the package. This +% is controlled by the \opt{scientific-notation} option, which takes +% choices \opt{false}, \opt{true}, \opt{fixed} and +% \opt{engineering}. The \opt{fixed} setting will use the exponent value +% by the \opt{fixed-exponent} option. When \opt{engineering} is set, +% the exponent is always a power of three. +%\begin{LaTeXdemo} +% \num{0.001} \\ +% \num{0.0100} \\ +% \num{1200} \\ +% \sisetup{scientific-notation = true}% +% \num{0.001} \\ +% \num{0.0100} \\ +% \num{1200} \\ +% \sisetup{scientific-notation = engineering}% +% \num{0.001} \\ +% \num{0.0100} \\ +% \num{1200} \\ +% \sisetup{ +% fixed-exponent = 2, +% scientific-notation = fixed, +% }% +% \num{0.001} \\ +% \num{0.0100} \\ +% \num{1200} +%\end{LaTeXdemo} +% When used with a \opt{fixed-exponent} of zero, this may be used to remove +% scientific notation from the input +%\begin{LaTeXdemo} +% \num{1.23e4} \\ +% \num[scientific-notation = fixed, fixed-exponent = 0]{1.23e4} +%\end{LaTeXdemo} +% Note that these options apply after any removal of unit mantissa, +% zero exponent, \emph{etc.} +% +% \DescribeOption{omit-uncertainty} +% The printing of an uncertainty can be suppressed entirely using the +% \opt{omit-uncertainty} option. +%\begin{LaTeXdemo} +% \num{0.01(2)} \\ +% \num[omit-uncertainty]{0.01(2)} +%\end{LaTeXdemo} +% +%\subsection{Printing numbers} +% +% Actually printing numbers is controlled by a number of settings, +% which apply ideas such as differing decimal markers, digit +% grouping and so on. All of these options are concerned with the +% appearance of output, rather than the data it conveys. The options are +% summarised in \cref{tab:opt:num:out}. +% +%\begin{table} +% \centering +% \caption{Output options for numbers.} +% \label{tab:opt:num:out} +% \begin{tabular}{>{\ttfamily}ll>{\ttfamily}l} +% \toprule +% \multicolumn{1}{l}{Option name} & +% Type & +% \multicolumn{1}{l}{Default} \\ +% \midrule +% bracket-negative-numbers & Switch & false \\ +% bracket-numbers & Switch & true \\ ^^A ( +% close-bracket & Literal & ) \\ +% complex-root-position & Choice & after-number \\ +% copy-complex-root & Choice & false \\ +% copy-decimal-marker & Choice & false \\ +% exponent-base & Literal & 10 \\ +% exponent-product & Math & \verb=\times= \\ +% group-digits & Choice & true \\ +% group-minimum-digits & integer & 5 \\ +% group-separator & Literal & \cs{,} \\ +% negative-color & Literal & \meta{none} \\ +% open-bracket & Literal & ( +% \\ ^^A ) ( +% output-close-uncertainty & Literal & ) \\ +% output-complex-root & Literal & \verb=\ensuremath{\mathrm{i}}= \\ +% output-decimal-marker & Literal & . \\ +% output-exponent-marker & Literal & \meta{none} \\ +% output-open-uncertainty & Literal & ( \\ ^^A ) +% separate-uncertainty & Switch & false \\ +% tight-spacing & Switch & false \\ +% uncertainty-separator & Literal & \meta{none} \\ +% \bottomrule +% \end{tabular} +%\end{table} +% +%\DescribeOption{group-digits} +%\changes{v2.2a}{2011/04/15}{Add missing default for \opt{group-digits} option} +% \changes{v2.3}{2011/06/06}{Extend \opt{group-digits} option, deprecating +% \opt{group-decimal-digits} and \opt{group-integer-digits}} +%\DescribeOption{group-four-digits} +%\DescribeOption{group-separator} +% Grouping digits into blocks of three is a common method to increase +% the ease of reading of numbers. The \opt{group-digits} choice controls +% whether this behaviour applies, and takes the values \opt{true}, \opt{false}, +% \opt{decimal} and \opt{integer}. Grouping can be activated separately for +% the integer and decimal parts of a number using the appropriately-named +% values. +%\begin{LaTeXdemo} +% \num{12345.67890} \\ +% \num[group-digits = false]{12345.67890} \\ +% \num[group-digits = decimal]{12345.67890} \\ +% \num[group-digits = integer]{12345.67890} +%\end{LaTeXdemo} +% The separator used between groups of digits is stored by the +% \opt{group-separator} option. This takes literal input and may be +% used in math mode: for a text-mode full space use |\text{~}|. +%\begin{LaTeXdemo} +% \num{12345} \\ +% \num[group-separator = {,}]{12345} \\ +% \num[group-separator = \text{~}]{12345} +%\end{LaTeXdemo} +% \DescribeOption{group-minimum-digits} +% \changes{v2.3}{2011/06/06}{New \opt{group-minimum-digits} option to +% replace \opt{group-four-digits}} +% Grouping is not always applied to smaller numbers, and the option +% \opt{group-minimum-digits} is available to specify how many digits must +% be present before grouping is applied. The number of digits is considered +% separately for the integer and decimal parts of the number: grouping +% does not \enquote{cross the boundary}. +%\begin{LaTeXdemo} +% \num{1234} \\ +% \num[group-minimum-digits = 4]{1234} \\ +% \num{1234.5678} \\ +% \num[group-minimum-digits = 4]{1234.5678} +%\end{LaTeXdemo} +% +%\DescribeOption{output-complex-root} +%\DescribeOption{output-decimal-marker} +%\DescribeOption{copy-complex-root} +%\changes{v2.1}{2010/10/02}{New \opt{copy-complex-root} option for +% moving input complex root to output} +%\DescribeOption{copy-decimal-marker} +% The decimal marker used in output is set using the +% \opt{output-decimal-marker} option. This can differ from the input +% marker, as can the root of $\sqrt{-1}$, which is stored in the +% \opt{output-complex-root} option. The standard setting uses \cs{mathrm} +% in math mode to give an upright +% \enquote{i}: this can easily be altered. The complex root or decimal +% marker from the input can be used in the output by setting the +% \opt{copy-complex-root} and \opt{copy-decimal-marker} options, +% respectively. +%\begin{LaTeXdemo} +% \num{1.23} \\ +% \num[output-decimal-marker = {,}]{1.23} \\ +% \num{1+2i} \\ +% \num[output-complex-root = \text{\ensuremath{i}}]{1+2i} \\ +% \num[output-complex-root = j]{1+2i} \\ +% \num[copy-complex-root]{1+2j} \\ +% \num[copy-decimal-marker]{555,555} +%\end{LaTeXdemo} +% +%\DescribeOption{complex-root-position} +% The position of the complex root can be adjusted to place it +% either before or after the associated numeral in a complex number +% using the \opt{complex-root-position} option. +%\begin{LaTeXdemo} +% \num{67-0.9i} \\ +% \num[complex-root-position = before-number]{67-0.9i} \\ +% \num[complex-root-position = after-number]{67-0.9i} +%\end{LaTeXdemo} +% +%\DescribeOption{exponent-base} +%\DescribeOption{exponent-product} +% When exponents are present in the input, the +% \opt{exponent-base} and \opt{exponent-product} options set the obvious +% parts of the output. Notice that the base is in the current mode, but +% the product sign is always in math mode. +%\begin{LaTeXdemo} +% \num[exponent-product = \times]{1e2} \\ +% \num[exponent-product = \cdot]{1e2} \\ +% \num[exponent-base = 2]{1e2} +%\end{LaTeXdemo} +%\DescribeOption{output-exponent-marker} +%\changes{v2.2}{2011/04/03}{New \opt{output-exponent-marker} option} +% Alternatively, if the \opt{output-exponent-marker} option is +% set then the value stored will be used in place of the normal +% product and base combination. This will normally be set up to +% ensure math or text mode. +%\begin{LaTeXdemo} +% \num[output-exponent-marker = \text{e}]{1e2} \\ +% \num[output-exponent-marker = \ensuremath{\mathrm{E}}]{1e2} +%\end{LaTeXdemo} +% +%\DescribeOption{separate-uncertainty} +%\DescribeOption{uncertainty-separator} +%\DescribeOption{output-open-uncertainty} +%\DescribeOption{output-close-uncertainty} +% When input is given including an uncertainty in a number, it can be +% printed either with the uncertainty in brackets or as a separate +% number. This behaviour is controlled by the +% \opt{separate-uncertainty} choice. If the uncertainty is given in +% brackets, a space may be added between the main number and the +% uncertainty: this is stored using the \opt{uncertainty-separator} +% option. The opening and closing brackets used are stored in +% \opt{output-open-uncertainty} and +% \opt{output-close-uncertainty}, respectively. +%\begin{LaTeXdemo} +% \num{1.234(5)} \\ +% \num[separate-uncertainty = true]{1.234(5)} \\ +% \sisetup{ +% output-open-uncertainty = [, +% output-close-uncertainty = ], +% uncertainty-separator = {\,} +% } +% \num{1.234(5)} +%\end{LaTeXdemo} +% Notice that \pkg{siunitx} correctly interprets uncertainties which +% cross the decimal marker position whether these are separated out +% or not. +%\begin{LaTeXdemo} +% \num{8.2(13)} \\ +% \num[separate-uncertainty]{8.2(13)} +%\end{LaTeXdemo} +% +%\DescribeOption{bracket-numbers} +%\DescribeOption{open-bracket} +%\DescribeOption{close-bracket} +% There are certain combinations of numerical input which can be +% ambiguous. This can be corrected by adding brackets in the appropriate +% place, and is controlled by the \opt{bracket-numbers} switch. The +% opening and closing brackets used are stored in \opt{open-bracket} and +% \opt{close-bracket}, respectively. Note that \opt{bracket-numbers} +% only applies to numbers without units: for numbers with units +% see the \opt{multi-part-units} option. +%\begin{LaTeXdemo} +% \num{1+2i e10} \\ +% \num[bracket-numbers = false]{1+2i e10} \\ +% \sisetup{ +% open-bracket = \{, +% close-bracket = \}, +% } +% \num{1+2i e10} +%\end{LaTeXdemo} +% +%\DescribeOption{negative-color} +% \pkg{siunitx} can detect negative mantissa values and alter print +% colour accordingly. This is disabled by setting the option to an empty +% value. +%\begin{LaTeXdemo} +% \num{-15673} \\ +% \num[negative-color = red]{-15673} +%\end{LaTeXdemo} +% +%\DescribeOption{bracket-negative-numbers} +%\changes{v2.2}{2011/04/02}{New \opt{bracket-negative-numbers} option} +% A common means to display negative numbers in financial situations +% is to place them in brackets. This can be carried out automatically +% using the \opt{bracket-negative-numbers} option. +%\begin{LaTeXdemo} +% \num{-15673} \\ +% \num[bracket-negative-numbers]{-15673} \\ +% \SI{-10}{\metre} \\ +% \SI[bracket-negative-numbers]{-10}{\metre} +%\end{LaTeXdemo} +% +%\DescribeOption{tight-spacing} +%\changes{v2.0y}{2010/10/09}{Error with \opt{tight-spacing} option +% and exponents corrected} +% Under some circumstances is may be desirable to \enquote{squeeze} +% the output spacing. This is turned on using the \opt{tight-spacing} +% switch, which compresses spacing where possible. +%\begin{LaTeXdemo} +% \num{1 \pm 2i e3} \\ +% \num[tight-spacing = true]{1 \pm 2i e3} +%\end{LaTeXdemo} +% +%\subsection{Multi-part numbers} +% +% \pkg{siunitx} recognises the idea of products and quotients in +% numbers, both with and without units. These multi-part numbers have +% a number of options affecting how they are processed. The options are +% summarised in \cref{tab:opt:num:multi}. +% +%\begin{table} +% \centering +% \caption{Multi-part number options.} +% \label{tab:opt:num:multi} +% \begin{tabular}{>{\ttfamily}ll>{\ttfamily}l} +% \toprule +% \multicolumn{1}{l}{Option name} & +% Type & +% \multicolumn{1}{l}{Default} \\ +% \midrule ^^A ( +% fraction-function & Macro & \cs{frac} \\ +% input-product & Literal & x \\ +% input-quotient & Literal & / \\ +% output-product & Math & \verb=\times= \\ +% output-quotient & Literal & / \\ +% quotient-mode & Choice & symbol \\ +% \bottomrule +% \end{tabular} +%\end{table} +% +%\DescribeOption{input-product} +%\DescribeOption{input-quotient} +% The options \opt{input-product} and \opt{input-quotient} contain the +% tokens used to determine if a number contains multiple parts. +%\begin{LaTeXdemo} +% \num{1 x 2 x 3} \\ +% \num{1e4 x 2(3) x 3/4} \\ +% \num[input-product=*]{4 * 5 * 6} \\ +% \num{ 1 / 2e4 } \\ +% \num{ 1e2 / 3e4 } +%\end{LaTeXdemo} +%\DescribeOption{output-product} +%\DescribeOption{output-quotient} +% The symbols used for printing products and quotients are stored using +% the options \opt{output-product} and \opt{output-quotient}. +%\begin{LaTeXdemo} +% \num[output-product = \cdot]{4.87 x 5.321 x 6.90545} \\ +% \num[output-quotient = \text{ div }]{1 / 2} +%\end{LaTeXdemo} +% +%\DescribeOption{quotient-mode} +% For quotients, there is the possibility to print output either using +% a slash, or using the \cs{frac} macro. This is controlled by the +% \opt{quotient} choice option, which takes values \opt{symbol} and +% \opt{fraction}. +%\begin{LaTeXdemo} +% \num{1 / 2e4} \\ +% \num[quotient-mode = fraction]{1 / 2e4} +%\end{LaTeXdemo} +% +%\DescribeOption{fraction-function} +% The function used when \opt{quotient-mode = fraction} is set is +% determined by the \opt{fraction-function} option. This should +% be set to a function which takes two arguments, and presumably +% creates some type of fraction. Most alternatives to the standard +% \cs{frac} function will involve loading additional packages: the +% demonstrations here need \pkg{amsmath} and +% \pkg{xfrac}. +%\begin{LaTeXdemo} +% \sisetup{quotient-mode = fraction} +% \num{1 / 1} +% \num[fraction-function = \dfrac]{1 / 2} +% \num[fraction-function = \sfrac]{1 / 3} +% \num[fraction-function = \tfrac]{1 / 4} +%\end{LaTeXdemo} +% +%\subsection{Lists and ranges of numbers} +% +% Lists and ranges of numbers have a small number of specialised +% options, which apply to these more unusual input forms +% (\cref{tab:opt:num:list}). +% +%\begin{table} +% \centering +% \caption{Output options for lists and ranges of numbers.} +% \label{tab:opt:num:list} +% \begin{tabular}{>{\ttfamily}ll>{\ttfamily}l} +% \toprule +% \multicolumn{1}{l}{Option name} & +% Type & +% \multicolumn{1}{l}{Default} \\ +% \midrule +% list-final-separator & Literal & \verb*= and = \\ +% list-pair-separator & Literal & \verb*= and = \\ +% list-separator & Literal & \verb*=, = \\ +% range-phrase & Literal & \verb*= to = \\ +% \bottomrule +% \end{tabular} +%\end{table} +% +% \DescribeOption{list-final-separator} +% \DescribeOption{list-pair-separator} +% \changes{v2.4}{2011/11/02}{New \opt{list-pair-separator} option} +% \DescribeOption{list-separator} +% Lists of numbers are printed with a separator between each item, +% which is stored using the \opt{list-separator} option. The +% separator before the last item of a list may be different, and +% is therefore set using the \opt{list-final-separator} option. +% The separator used for exactly two items is set using the +% \opt{list-pair-separator} option. Any +% spaces needed should be included in the option settings: none are +% added within the code. These items are printed in text mode. +%\begin{LaTeXdemo} +% \numlist{0.1;0.2;0.3} \\ +% \numlist[list-separator = {; }]{0.1;0.2;0.3} \\ +% \numlist[list-final-separator = {, }]{0.1;0.2;0.3} \\ +% \numlist[ +% list-separator = { and }, +% list-final-separator = { and finally } +% ]{0.1;0.2;0.3} \\ +% \numlist{0.1;0.2} \\ +% \numlist[list-pair-separator = {, and }]{0.1;0.2} +%\end{LaTeXdemo} +% +%\DescribeOption{range-phrase} +% Ranges of numbers can be given as input. These will have an +% appropriate word or symbol inserted between the two entries: this +% is stored using the \opt{range-phrase} option. The phrase should +% include any necessary spaces: no extra space is added. +%\begin{LaTeXdemo} +% \numrange{5}{100} \\ +% \numrange[range-phrase = --]{5}{100} +%\end{LaTeXdemo} +% +% \changes{v2.4}{2011/11/04}{Automatically compress exponents for lists and +% ranges when fixed exponents are active} +% For lists and ranges when a single unit is given, \pkg{siunitx} will +% automatically \enquote{compress} exponents when a fixed exponent is in +% use. +%\begin{LaTeXdemo} +% \sisetup{ +% fixed-exponent = 3 , +% list-units = brackets , +% range-units = brackets , +% scientific-notation = fixed +% }% +% \SIrange{1e3}{7e3}{\metre} \\ +% \SIlist{1e3;2e3;3e3}{\kg} +%\end{LaTeXdemo} +% +%\subsection{Angles} +% +% Angle processing provided by the \cs{ang} function has a set of +% options which apply in addition to the general ones set up for number +% processing (\cref{tab:opt:ang}). +% +%\begin{table} +% \centering +% \caption{Angle options.} +% \label{tab:opt:ang} +% \begin{tabular}{>{\ttfamily}ll>{\ttfamily}l} +% \toprule +% \multicolumn{1}{l}{Option name} & +% Type & +% \multicolumn{1}{l}{Default} \\ +% \midrule +% add-arc-degree-zero & Switch & false \\ +% add-arc-minute-zero & Switch & false \\ +% add-arc-second-zero & Switch & false \\ +% angle-symbol-over-decimal & Switch & false \\ +% arc-separator & Literal & \meta{empty} \\ +% number-angle-product & Literal & \meta{empty} \\ +% \bottomrule +% \end{tabular} +%\end{table} +% +%\DescribeOption{number-angle-product} +% The separator between the number and angle symbol (degrees, minutes +% or seconds) can be set using the \opt{number-angle-product} +% option, independent of the related \opt{number-unit-product} +% option used by the \cs{SI} function. +%\begin{LaTeXdemo} +% \ang{2.67} \\ +% \ang[number-angle-product = \,]{2.67} +%\end{LaTeXdemo} +% +%\DescribeOption{arc-separator} +% When angles are printed in arc format, the separation of the different +% parts is set up using the \opt{arc-separator} option. +%\begin{LaTeXdemo} +% \ang{6;7;6.5} \\ +% \ang[arc-separator = \,]{6;7;6.5} +%\end{LaTeXdemo} +% +%\DescribeOption{add-arc-degree-zero} +%\DescribeOption{add-arc-minute-zero} +%\DescribeOption{add-arc-second-zero} +% Zero-filling for the degree, minute or second parts of an arc is +% controlled using the \opt{add-arc-degree-zero}, +% \opt{add-arc-minute-zero} and \opt{add-arc-second-zero} options. +% All are off as standard. +%\begin{LaTeXdemo} +% \ang{-1;;} \\ +% \ang{;-2;} \\ +% \ang{;;-3} \\ +% \sisetup{add-arc-degree-zero} +% \ang{-1;;} \\ +% \ang{;-2;} \\ +% \ang{;;-3} \\ +% \sisetup{add-arc-minute-zero} +% \ang{-1;;} \\ +% \ang{;-2;} \\ +% \ang{;;-3} \\ +% \sisetup{add-arc-second-zero} +% \ang{-1;;} \\ +% \ang{;-2;} \\ +% \ang{;;-3} +%\end{LaTeXdemo} +% +%\DescribeOption{angle-symbol-over-decimal} +% In some subject areas, most notably astronomy, the angle symbols +% are given over the decimal marker, rather than at the end of the +% number. This behaviour is available using the +% \opt{angle-symbol-over-decimal} option. +%\begin{LaTeXdemo} +% \ang{45.697} \\ +% \ang{6;7;6.5} \\ +% \ang[angle-symbol-over-decimal]{45.697} \\ +% \ang[angle-symbol-over-decimal]{6;7;6.5} +%\end{LaTeXdemo} +% +%\subsection{Creating units} +%\label{sec:units:creating} +% +% The various macro units are created at the start of the document. +% \pkg{siunitx} can define these such that they are only available for +% use within the \cs{si} and \cs{SI} functions, or can make the unit +% macros available throughout the document body. There are a number of +% settings which control this creation process +% (\cref{tab:opt:units:def}). As a result, these options all apply +% in the preamble only. +% +%\begin{table} +% \centering +% \caption{Unit creation options.} +% \label{tab:opt:units:def} +% \begin{tabular}{>{\ttfamily}ll>{\ttfamily}l} +% \toprule +% \multicolumn{1}{l}{Option name} & +% Type & +% \multicolumn{1}{l}{Default} \\ +% \midrule ^^A ( +% free-standing-units & Switch & false \\ +% overwrite-functions & Switch & false \\ +% space-before-unit & Switch & false \\ +% unit-optional-argument & Switch & false \\ +% use-xspace & Switch & false \\ +% \bottomrule +% \end{tabular} +%\end{table} +% +%\DescribeOption{free-standing-units} +%\changes{v2.1d}{2010/11/14}{Apply unit options when +% \opt{free-standing-units} is active} +%\changes{v2.1e}{2010/11/22}{Further corrections when applying unit +% options when \opt{free-standing-units} is active} +%\DescribeOption{overwrite-functions} +% The \opt{free-standing-units} option controls whether the unit macros +% exist outside of the \cs{si} and \cs{SI} arguments. When this option +% is \opt{true}, \pkg{siunitx} creates the macros for general use. +% The standard method to achieve this does not overwrite any existing +% macros: this behaviour can be altered using the +% \opt{overwrite-functions} switch. +% +%\DescribeOption{space-before-unit} +%\DescribeOption{unit-optional-argument} +%\changes{v2.1f}{2010/11/24}{Typo in definition for +% \opt{unit-optional-argument} implementation corrected} +%\DescribeOption{use-xspace} +% When \enquote{free standing} unit macros are created, their behaviour +% can be adjusted by a number of options. These are mainly intended for +% emulating the input syntax of older packages. The option +% \opt{unit-optional-argument} gives the same behaviour for the +% inputs +%\begin{LaTeXdemo}[code only] +% \SI{10}{\metre} +%\end{LaTeXdemo} +% and +%\begin{LaTeXdemo}[code only] +% \metre[10]. +%\end{LaTeXdemo} +% The \opt{space-before-unit} and \opt{use-xspace} options control +% the behaviour at the \enquote{ends} of the unit macros. Activating +% \opt{space-before-unit} inserts the number--unit space before the +% unit is printed. This is suitable for the input syntax +%\begin{LaTeXdemo}[code only] +% 30\metre +%\end{LaTeXdemo} +% but does mean that the unit macros are incorrectly spaced in running +% text. On the other hand, the \opt{use-xspace} option attempts to +% correctly space input such as +%\begin{LaTeXdemo}[code only] +% \metre is the symbol for metres. +%\end{LaTeXdemo} +% +%\subsection{Loading additional units} +% +% \DescribeOption{abbreviations} +% As standard, \pkg{siunitx} loads a set of abbreviated versions of the +% SI units (\cref{tab:unit:abbr}). The standard \pkg{siunitx} settings only +% create these abbreviations within the scope of the \cs{si} and \cs{SI} +% functions, meaning that no clashes should occur (for example with the +% standard \cs{pm} symbol). Loading of these abbreviations can be prevented +% by setting the option \opt{abbreviations = false} in the preamble. +% +%\begin{center} +% \changes{v2.0n}{2010/07/15}{More abbreviated units} +% \changes{v2.3b}{2011/07/27}{More abbreviated units} +% \tablecaption{Abbreviated units.} +% \label{tab:unit:abbr} +% \tablefirsthead{^^A +% \toprule +% \multicolumn{1}{l}{Unit} & +% \multicolumn{1}{l}{Abbreviation} & +% \multicolumn{1}{l}{Symbol} \\ +% \midrule +% } +% \tablehead{^^A +% \multicolumn{3}{l}{\emph{Continued from previous page}} \\ +% \toprule +% \multicolumn{1}{l}{Unit} & +% \multicolumn{1}{l}{Abbreviation} & +% \multicolumn{1}{l}{Symbol} \\ +% \midrule +% } +% \tabletail{^^A +% \bottomrule +% \multicolumn{3}{r}{\emph{Continued on next page}} \\ +% } +% \tablelasttail{\bottomrule} +% \begin{xtabular}{lcc} +% \DescribeNamedUnit{femtogram}{fg} \\ +% \DescribeNamedUnit{picogram}{pg} \\ +% \DescribeNamedUnit{nanogram}{ng} \\ +% \DescribeNamedUnit{microgram}{ug} \\ +% \DescribeNamedUnit{milligram}{mg} \\ +% \DescribeNamedUnit{gram}{g} \\ +% \DescribeNamedUnit{kilogram}{kg} \\ +% \DescribeNamedUnit{atomic mass unit}{amu} \\ +% +% \midrule +% +% \DescribeNamedUnit{picometre}{pm} \\ +% \DescribeNamedUnit{nanometre}{nm} \\ +% \DescribeNamedUnit{micrometre}{um} \\ +% \DescribeNamedUnit{millimetre}{mm} \\ +% \DescribeNamedUnit{centimetre}{cm} \\ +% \DescribeNamedUnit{decimetre}{dm} \\ +% \DescribeNamedUnit{metre}{m} \\ +% \DescribeNamedUnit{kilometre}{km} \\ +% +% \midrule +% +% \DescribeNamedUnit{attosecond}{as} \\ +% \DescribeNamedUnit{femtosecond}{fs} \\ +% \DescribeNamedUnit{picosecond}{ps} \\ +% \DescribeNamedUnit{nanosecond}{ns} \\ +% \DescribeNamedUnit{microsecond}{us} \\ +% \DescribeNamedUnit{millisecond}{ms} \\ +% \DescribeNamedUnit{second}{s} \\ +% +% \midrule +% +% \DescribeNamedUnit{femtomole}{fmol} \\ +% \DescribeNamedUnit{picomole}{pmol} \\ +% \DescribeNamedUnit{nanomole}{nmol} \\ +% \DescribeNamedUnit{micromole}{umol} \\ +% \DescribeNamedUnit{millimole}{mmol} \\ +% \DescribeNamedUnit{mole}{mol} \\ +% \DescribeNamedUnit{kilomole}{kmol} \\ +% +% \midrule +% +% \DescribeNamedUnit{picoampere}{pA} \\ +% \DescribeNamedUnit{nanoampere}{nA} \\ +% \DescribeNamedUnit{microampere}{uA} \\ +% \DescribeNamedUnit{milliampere}{mA} \\ +% \DescribeNamedUnit{ampere}{A} \\ +% \DescribeNamedUnit{kiloampere}{kA} \\ +% +% \midrule +% +% \DescribeNamedUnit{microlitre}{ul} \\ +% \DescribeNamedUnit{millilitre}{ml} \\ +% \DescribeNamedUnit{litre}{l} \\ +% \DescribeNamedUnit{hectolitre}{hl} \\ +% \DescribeNamedUnit{microliter}{uL} \\ +% \DescribeNamedUnit{milliliter}{mL} \\ +% \DescribeNamedUnit{liter}{L} \\ +% \DescribeNamedUnit{hectoliter}{hL} \\ +% +% \midrule +% +% \DescribeNamedUnit{millihertz}{mHz} \\ +% \DescribeNamedUnit{hertz}{Hz} \\ +% \DescribeNamedUnit{kilohertz}{kHz} \\ +% \DescribeNamedUnit{megahertz}{MHz} \\ +% \DescribeNamedUnit{gigahertz}{GHz} \\ +% \DescribeNamedUnit{terahertz}{THz} \\ +% +% \midrule +% +% \DescribeNamedUnit{millinewton}{mN} \\ +% \DescribeNamedUnit{newton}{N} \\ +% \DescribeNamedUnit{kilonewton}{kN} \\ +% \DescribeNamedUnit{meganewton}{MN} \\ +% +% \midrule +% +% \DescribeNamedUnit{pascal}{Pa} \\ +% \DescribeNamedUnit{kilopascal}{kPa} \\ +% \DescribeNamedUnit{megapacal}{MPa} \\ +% \DescribeNamedUnit{gigapascal}{GPa} \\ +% +% \midrule +% +% \DescribeNamedUnit{milliohm}{mohm} \\ +% \DescribeNamedUnit{kilohm}{kohm} \\ +% \DescribeNamedUnit{megohm}{Mohm} \\ +% +% \midrule +% +% \DescribeNamedUnit{picovolt}{pV} \\ +% \DescribeNamedUnit{nanovolt}{nV} \\ +% \DescribeNamedUnit{microvolt}{uV} \\ +% \DescribeNamedUnit{millivolt}{mV} \\ +% \DescribeNamedUnit{volt}{V} \\ +% \DescribeNamedUnit{kilovolt}{kV} \\ +% +% \midrule +% +% \DescribeNamedUnit{watt}{W} \\ +% \DescribeNamedUnit{microwatt}{uW} \\ +% \DescribeNamedUnit{milliwatt}{mW} \\ +% \DescribeNamedUnit{kilowatt}{kW} \\ +% \DescribeNamedUnit{megawatt}{MW} \\ +% \DescribeNamedUnit{gigawatt}{GW} \\ +% \DescribeNamedUnit{joule}{J} \\ +% \DescribeNamedUnit{microjoule}{uJ} \\ +% \DescribeNamedUnit{millijoule}{mJ} \\ +% \DescribeNamedUnit{kilojoule}{kJ} \\ +% \DescribeNamedUnit{electronvolt}{eV} \\ +% \DescribeNamedUnit{millielectronvolt}{meV} \\ +% \DescribeNamedUnit{kiloelectronvolt}{keV} \\ +% \DescribeNamedUnit{megaelectronvolt}{MeV} \\ +% \DescribeNamedUnit{gigaelectronvolt}{GeV} \\ +% \DescribeNamedUnit{teraelectronvolt}{TeV} \\ +% \DescribeNamedUnit{kilowatt hour}{kWh} \\ +% +% \midrule +% +% \DescribeNamedUnit{farad}{F} \\ +% \DescribeNamedUnit{femtofarad}{fF} \\ +% \DescribeNamedUnit{picofarad}{pF} \\ +% +% \midrule +% +% \DescribeNamedUnit{kelvin}{K} \\ +% +% \midrule +% +% \DescribeNamedUnit{decibel}{dB} \\ +% +% \end{xtabular} +%\end{center} +% +% \DescribeOption{binary-units} +% \DescribeMacro{\bit} +% \DescribeMacro{\byte} +% Binary data is expressed in units of bits and bytes. These are +% normally given prefixes which use powers of two, rather than the +% powers of ten used by the SI prefixes. As these binary prefixes are +% closely related to the SI prefixes, they are defined by \pkg{siunitx} +% but do have to be loaded using \opt{binary-units = true} (or +% simply \opt{binary-units}) +% (\cref{tab:unit:binary}). The units \cs{bit} and \cs{byte} are +% then also available. +%\begin{LaTeXdemo} +% \SI{100}{\mebi\byte} \\ +% \SI[prefixes-as-symbols=false]{30}{\kibi\bit} +%\end{LaTeXdemo} +% +%\begin{table} +% \caption{Binary prefixes.} +% \label{tab:unit:binary} +% \centering +% \begin{tabular}{llc>{$}l<{$}} +% \toprule +% Prefix & Macro & Symbol & \multicolumn{1}{l}{Power} \\ +% \midrule +% \DescribePrefix{kibi} & 10 \\ +% \DescribePrefix{mebi} & 20 \\ +% \DescribePrefix{gibi} & 30 \\ +% \DescribePrefix{tebi} & 40 \\ +% \DescribePrefix{pebi} & 50 \\ +% \DescribePrefix{exbi} & 60 \\ +% \DescribePrefix{zebi} & 70 \\ +% \DescribePrefix{yobi} & 80 \\ +% \bottomrule +% \end{tabular} +%\end{table} +% +% \DescribeOption{version-1-compatibility} +% A configuration file is also included which will use settings +% and define macros as defined by version 1 of \pkg{siunitx}: this +% can be accessed with the option \opt{version-1-compatibility}. +% This is intended to allow easy transition to version 2: users +% should update their source to use the new interfaces and functions. +% +% Users upgrading from version 1 of \pkg{siunitx} will notice that +% the various \enquote{specialist} units available in version 1 are +% no longer provided as loadable options.\footnote{They are included +% in the loaded configuration file \opt{version-1}, but this is intended +% purely to ease transition to version 2.} These are not included in +% version 2 as the criteria for inclusion of such units are far from +% clear, and it is difficult to justify providing clearly non-SI +% units in the package. For reference, appropriate definitions for +% the units which where provided in version 1 are as follows. +%\begin{LaTeXdemo}[code only] +% % Astronomy +% \DeclareSIUnit\parsec{pc} +% \DeclareSIUnit\lightyear{ly} +% +% % Chemical engineering +% \DeclareSIUnit\gmol{g\text{-}mol} +% \DeclareSIUnit\kgmol{kg\text{-}mol} +% \DeclareSIUnit\lbmol{lb\text{-}mol} +% +% % Chemistry +% \DeclareSIUnit\molar{\mole\per\cubic\deci\metre} +% \DeclareSIUnit\Molar{\textsc{m}} +% \DeclareSIUnit\torr{torr} +% +% % Geophysics +% \DeclareSIUnit\gon{gon} +% +% % High energy physics +% \DeclareSIUnit\micron{\micro\metre} +% \DeclareSIUnit\mrad{\milli\rad} +% \DeclareSIUnit\gauss{G} +% \DeclareSIUnit\eVperc{\eV\per\clight} +% \DeclareSIUnit\nanobarn{\nano\barn} +% \DeclareSIUnit\picobarn{\pico\barn} +% \DeclareSIUnit\femtobarn{\femto\barn} +% \DeclareSIUnit\attobarn{\atto\barn} +% \DeclareSIUnit\zeptobarn{\zepto\barn} +% \DeclareSIUnit\yoctobarn{\yocto\barn} +% \DeclareSIUnit\nb{\nano\barn} +% \DeclareSIUnit\pb{\pico\barn} +% \DeclareSIUnit\fb{\femto\barn} +% \DeclareSIUnit\ab{\atto\barn} +% \DeclareSIUnit\zb{\zepto\barn} +% \DeclareSIUnit\yb{\yocto\barn} +%\end{LaTeXdemo} +% Users can use a local configuration file to make additional units +% available on a local basis, as described in \cref{sec:config:local}. +% +%\subsection{Using units} +% +% Part of the power of \pkg{siunitx} is the ability to alter the output +% format for units without changing the input. The behaviour of units +% is therefore controlled by a number of options which alter either the +% processing of units or the output directly +% (\cref{tab:opt:units:out}). +% +%\begin{table} +% \centering +% \caption{Unit output options.} +% \label{tab:opt:units:out} +% \begin{tabular}{>{\ttfamily}ll>{\ttfamily}l} +% \toprule +% \multicolumn{1}{l}{Option name} & +% Type & +% \multicolumn{1}{l}{Default} \\ +% \midrule +% bracket-unit-denominator & Switch & true \\ +% forbid-literal-units & Switch & false \\ +% literal-superscript-as-power & Switch & true \\ +% inter-unit-product & Literal & \cs{,} \\ +% parse-units & Switch & true \\ +% per-mode & Choice & reciprocal \\ +% per-symbol & Literal & / \\ +% power-font & Choice & number \\ +% prefixes-as-symbols & Switch & true \\ +% qualifier-mode & Choice & subscript \\ +% sticky-per & Switch & false \\ +% \bottomrule +% \end{tabular} +%\end{table} +% +%\DescribeOption{forbid-literal-units} +% Some users may prefer to completely disable the use of literal input +% in units, for example to enforce consistency. This can be +% accomplished by setting the \opt{forbid-literal-units} switch. With +% this option enabled, only macro-based units can be used in a document. +% +%\DescribeOption{inter-unit-product} +% The separator between each unit is stored using the +% \opt{inter-unit-product} option. The standard setting is a thin +% space: another common choice is a centred dot. To get the correct +% spacing it is necessary to use |\ensuremath{{}\cdot{}}| in the latter case. +%\begin{LaTeXdemo} +% \si{\farad\squared\lumen\candela} \\ +% \si[inter-unit-product = \ensuremath{{}\cdot{}}] +% {\farad\squared\lumen\candela} +%\end{LaTeXdemo} +% +%\DescribeOption{per-mode} +%\changes{v2.1i}{2011/01/27}{Improved logic for \opt{per-mode} setting +% \opt{symbol-or-fraction}} +%\changes{v2.2}{2011/04/05}{Include leading \( 1 \) when \opt{per-mode} +% is set to \opt{symbol} and there are no numerator units in \cs{si} +% arguments} +%\DescribeOption{per-symbol} +%\DescribeOption{bracket-unit-denominator} +% The handling of \cs{per} is altered using the \opt{per-mode} choice +% option. The standard setting is \opt{reciprocal}, meaning that +% \cs{per} generates reciprocal powers for units. Setting the option +% to \opt{fraction} uses the \cs{frac} function to typeset the positive +% and negative powers of a unit separately. +%\begin{LaTeXdemo} +% \si{\joule\per\mole\per\kelvin} \\ +% \si{\metre\per\second\squared} \\ +% \si[per-mode=fraction]{\joule\per\mole\per\kelvin} \\ +% \si[per-mode=fraction]{\metre\per\second\squared} +%\end{LaTeXdemo} +% The closely-related \opt{reciprocal-positive-first} setting acts in +% the same way but places all of the positive powers before any negative +% ones. +%\begin{LaTeXdemo} +% \si{\ampere\per\mole\second} \\ +% \si[per-mode = reciprocal-positive-first] +% {\ampere\per\mole\second} +%\end{LaTeXdemo} +% It is possible to use a symbol (usually \texttt{/}) to separate the +% two parts of a unit by setting \opt{per-mode} to \opt{symbol}; the +% symbol used is stored using the setting \opt{per-symbol}. This method +% for displaying units can be ambiguous, and so brackets are added +% unless \opt{bracket-unit-denominator} is set to \opt{false}. +% Notice that \opt{bracket-unit-denominator} only applies when +% \opt{per-mode} is set to \opt{symbol} or \opt{symbol-or-fraction}. +%\begin{LaTeXdemo} +% \sisetup{per-mode = symbol}% +% \si{\joule\per\mole\per\kelvin} \\ +% \si{\metre\per\second\squared} \\ +% \si[per-symbol = \text{~div~}]{\joule\per\mole\per\kelvin} \\ +% \si[bracket-unit-denominator = false]{\joule\per\mole\per\kelvin} +%\end{LaTeXdemo} +% The often-requested (but mathematically invalid) +% \opt{repeated-symbol} option is also available to repeat the symbol +% for each \cs{per}. +%\begin{LaTeXdemo} +% \si[per-mode=repeated-symbol]{\joule\per\mole\per\kelvin} +%\end{LaTeXdemo} +% Finally, it is possible for the behaviour of the \cs{per} function +% to depend on the prevailing math style. Setting \opt{per-mode} to +% \opt{symbol-or-fraction} will use the \opt{symbol} setting for +% in line math, and the \opt{fraction} setting when used in +% \cs{displaystyle} math. +%\begin{LaTeXdemo} +% \sisetup{per-mode = symbol-or-fraction}% +% \( \si{\joule\per\mole\per\kelvin} \) +% \[ \si{\joule\per\mole\per\kelvin} \] +% \si{\joule\per\mole\per\kelvin} \\ +% \( +% \displaystyle +% \si{\joule\per\mole\per\kelvin} +% \) +% \[ +% \textstyle +% \si{\joule\per\mole\per\kelvin} +% \] +%\end{LaTeXdemo} +% +%\DescribeOption{sticky-per} +% By default, \cs{per} applies only to the next unit +% given.\footnote{This is the standard method of reading units in +% English: for example, \si{\joule\per\mole\per\kelvin} is pronounced +% \enquote{joules per mole per kelvin}.} By setting the +% \opt{sticky-per} flag, this behaviour is changed so that \cs{per} +% applies to all subsequent units. +%\begin{LaTeXdemo} +% \si{\pascal\per\gray\henry} \\ +% \si[sticky-per]{\pascal\per\gray\henry} +%\end{LaTeXdemo} +% +%\DescribeOption{power-font} +%\changes{v2.1}{2010/10/12}{New \opt{power-font} option for controlling +% whether superscript powers are treated as numbers or units} +% The font used for the powers in units can be typeset using the +% current number or unit font. This may be of use when the font used +% for numbers and units are very different, for example when the +% \pkg{euler} package is loaded. Note that this setting applies to all +% printing options for numbers, including the color used for displaying +% the number. +%\begin{LaTeXdemo} +% \si{\metre\per\second\squared} \\ +% \si[power-font = unit]{\metre\per\second\squared} +%\end{LaTeXdemo} +% \DescribeOption{literal-superscript-as-power} +% \changes{v2.3}{2011/06/08}{New \opt{literal-superscript-as-power} option for +% controlling how literal units superscripts behave} +% When printing units in \enquote{literal} mode, it is possible that simply +% printing superscripts \enquote{as is} may lead to poor appearance for the +% numbers. This is most likely if the text font of the document uses +% old style (lower case) numerals, but the math font uses lining (upper +% case) numerals. It is therefore possible to treat superscripts within +% literal units as powers, and thus for the \opt{power-font} option to +% apply within these literal units. This behaviour is controlled using the +% \opt{literal-superscript-as-power} switch. +%\begin{LaTeXdemo} +% \si{m.s^{2}} \\ +% \si[literal-superscript-as-power = false]{m.s^{2}} +%\end{LaTeXdemo} +% +%\DescribeOption{qualifier-mode} +%\changes{v2.1c}{2010/11/13}{New \opt{text} choice for +% \opt{qualifier-mode} option} +% \DescribeOption{qualifier-phrase} +% Unit qualifiers can be printed in three different formats, set by the +% \opt{qualifier-mode} option. The standard setting is \opt{subscript}, +% while the options \opt{brackets}, \opt{phrase}, \opt{space} and \opt{text} +% are also possible. With the last settings, powers can lead to ambiguity and +% are automatically detected and brackets added as appropriate. +%\begin{LaTeXdemo} +% \si{\kilogram\polymer\squared\per\mole\catalyst\per\hour} \\ +% \si[qualifier-mode = brackets] +% {\kilogram\polymer\squared\per\mole\catalyst\per\hour} \\ +% \si[qualifier-mode = subscript] +% {\kilogram\polymer\squared\per\mole\catalyst\per\hour} \\ +% \si[qualifier-mode = space] +% {\kilogram\polymer\squared\per\mole\catalyst\per\hour} \\ +% \si[qualifier-mode = text] +% {\deci\bel\isotropic} +%\end{LaTeXdemo} +% The \opt{phrase} setting for \opt{qualifier-mode} uses the text stored using +% \opt{qualifier-phrase} to separate the qualifier. +%\begin{LaTeXdemo} +% \si[qualifier-mode = phrase] +% {\kilogram\polymer\squared\per\mole\catalyst\per\hour} \\ +% \si[qualifier-mode = phrase, qualifier-phrase = { by }] +% {\kilogram\polymer\squared\per\mole\catalyst\per\hour} \\ +%\end{LaTeXdemo} +% +%\DescribeOption{prefixes-as-symbols} +% The unit prefixes (\cs{kilo}, \emph{etc}.) are normally given as +% letters. However, the package can convert these into numerical powers. +% This is controlled by the \opt{prefixes-as-symbols} switch option. +% This correctly deals with the kilogram, which is a base unit even +% though it involves a prefix. +%\begin{LaTeXdemo} +% \si{\milli\litre\per\mole\deci\ampere} \\ +% \SI{10}{\kilo\gram\squared\deci\second} \\ +% \si[prefixes-as-symbols=false]{\milli\litre\per\mole\deci\ampere}\\ +% \SI[prefixes-as-symbols=false]{10}{\kilo\gram\squared\deci\second} +%\end{LaTeXdemo} +% +%\DescribeOption{parse-units} +% Normally, \pkg{siunitx} is used with the unit parse enabled, and +% only prints units directly if there is literal input. However, if +% the input is known to be essentially consistent and high performance +% is desired, then the parser can be turned off using the +% \opt{parse-units} switch. +%\begin{LaTeXdemo} +% \SI{300}{\MHz} \\ +% \SI[parse-units = false]{300}{\MHz} +%\end{LaTeXdemo} +% +%\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 & \meta{see text} \\ +% 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 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, German and Spanish as options, and also loads the +% \pkg{babel} package: +%\begin{LaTeXdemo} +% % In English by default +% \SIlist{1;2;3}{\metre} \\ +% \SIrange{1}{10}{\degreeCelsius} \\ +% \selectlanguage{french}% +% \SIlist{1;2;3}{\metre} \\ +% \SIrange{1}{10}{\degreeCelsius} \\ +% \selectlanguage{german}% +% \SIlist{1;2;3}{\metre} \\ +% \SIrange{1}{10}{\degreeCelsius} \\ +% \selectlanguage{spanish}% +% \SIlist{1;2;3}{\metre} \\ +% \SIrange{1}{10}{\degreeCelsius} \\ +%\end{LaTeXdemo} +% +% Note that the in order for this to work correctly, languages should +% be given as global (class) options rather than as package options +% for \pkg{babel}. +% +%\section{Hints for using \pkg{siunitx}} +% +%\subsection{Ensuring text or math output} +% +% The macros \cs{ensuremath} and \cs{text} should be used to ensure that +% a particular item is always printed in the desired mode. Some +% mathematical output does not work well in \cs{mathrm} (the standard +% font used by \pkg{siunitx} for printing). The easiest way to solve +% this is to use the construction "\text{\ensuremath{...}}", which will +% print the material in the standard mathematics font without affecting +% the rest of the output. In some cases, simply forcing \cs{mathnormal} +% will suffice, but this is less reliable with non-Latin characters. +% +%\subsection{Expanding content in tables} +%\label{sec:expanding} +% +% When processing tables, \pkg{siunitx} will expand anything stored +% inside a macro, unless it is long or protected. \LaTeXe{} robust +% commands are also detected and are not expanded +% (\cref{tab:xmpl:macro}). Values which would otherwise be expanded +% can be protected by wrapping them in a set of braces. As \TeX{} itself +% will expand the first token in a table cell before \pkg{siunitx} +% can act on it, using the \eTeX{} protected mechanism is the +% recommended course of action to prevent expansion of macros in +% table cells. (As is shown in the table, \TeX's expansion of +% \LaTeXe{} robust commands can lead to unexpected results.) +%\begin{LaTeXdemo}[code and float] +% \begin{table} +% \centering +% \caption{Values as macros in \texttt{S} columns.} +% \label{tab:xmpl:macro} +% \newcommand*\myvaluea{1234} +% \newcommand\myvalueb{1234} +% \DeclareRobustCommand*\myvaluec{1234} +% \protected\def\myvalued{1234} +% \begin{tabular}{S} +% \toprule +% {Some Values} \\ +% \midrule +% \myvaluea 8.8 \myvaluea \\ % Both expanded +% \myvalueb 8.8 \myvalueb \\ % First expanded by TeX +% % to numbers +% \myvaluec 8.8 \myvaluec \\ % First expanded by TeX +% % but not to numbers! +% \myvalued 8.8 \myvalued \\ % Neither expanded +% {\myvaluea\ 8.8 \myvaluea} \\ % Neither expanded +% \bottomrule +% \end{tabular} +% \end{table} +%\end{LaTeXdemo} +% +% It is possible to use calculated values in tables. For this to +% work, the calculation must take place before attempting to parse +% the number. An added complication is that \TeX{} itself will +% expand the first macro in a table cell until it finds +% something unexpandable. The \eTeX{} protected mechanism can be +% used to prevent this; using the \pkg{etoolbox} package provides +% a convenient way to apply this protection to existing functions. +% The general approach is illustrated in \cref{tab:xmpl:calc}. +% The macro \cs{DTLmul} is made robust inside the table using +% the \cs{robustify} command from \pkg{etoolbox}, before +% constructing the table using an extra column to contain the +% calculation. +%\begin{LaTeXdemo}[code and float] +% \DTLnewdb{data} +% \DTLnewrow{data}\DTLnewdbentry{data}{value}{66.7012} +% \DTLnewrow{data}\DTLnewdbentry{data}{value}{66.0212} +% \DTLnewrow{data}\DTLnewdbentry{data}{value}{64.9026} +% \begin{table} +% \caption{Calculated values.} +% \label{tab:xmpl:calc} +% \centering +% \robustify\DTLmul +% \sisetup{ +% table-number-alignment = center, +% table-figures-integer = 2, +% table-figures-decimal = 4 +% } +% \begin{tabular}{ +% S +% S[table-figures-integer = 3] +% @{}l +% } +% \toprule +% {Value} & {Doubled} & +% \DTLforeach{data}{\myvalue=value}{% +% \DTLiffirstrow {\\ \midrule}{\\}% +% \myvalue & % First column +% \DTLmul{\myvalue}{\myvalue}{2} \myvalue % second column +% & }\\ +% \bottomrule +% \end{tabular} +% \end{table} +%\end{LaTeXdemo} +% +%\subsection{Using \pkg{siunitx} with \pkg{datatool}} +% +% As illustrated in \cref{tab:xmpl:calc}, \pkg{siunitx} can be used +% to typeset data stored using \pkg{datatool}. For quickly displaying +% the contents of tables, \pkg{datatool} offers the \cs{DTLshowtable} +% macro. This will only work with \texttt{S} columns if number parsing +% is turned off (\cref{tab:xmpl:datatool}). +%\begin{LaTeXdemo}[code and float] +% \DTLnewdb{moredata} +% \DTLnewrow{moredata}\DTLnewdbentry{moredata}{value}{ 6.7012} +% \DTLnewrow{moredata}\DTLnewdbentry{moredata}{value}{66.0212} +% \DTLnewrow{moredata}\DTLnewdbentry{moredata}{value}{64.902 } +% \begin{table} +% \caption{Displaying a \textsf{datatool} table.} +% \label{tab:xmpl:datatool} +% \centering +% \sisetup{ +% parse-numbers = false, +% table-number-alignment = center, +% table-figures-integer = 2, +% table-figures-decimal = 4 +% } +% \renewcommand*\dtlrealalign{S} +% \DTLdisplaydb{moredata} +% \end{table} +%\end{LaTeXdemo} +% +%\subsection{Using units such as \si{\micro\metre\per\second} in +% headings} +% +% The \pkg{siunitx} code is designed to work correctly with functions +% in headings. They will print correctly in headings and in the table +% of contents. As illustrated here, the standard behaviour is to ignore +% font changes. When the \pkg{hyperref} package is loaded, the +% functions automatically \enquote{degrade gracefully} to produce +% useful information in PDF bookmarks. If you want more control over +% the bookmark text, use the \cs{texorpdfstring} function from +% \pkg{hyperref}, for example: +%\begin{LaTeXdemo}[code only] +% \section{Some text +% \texorpdfstring +% {\si{\joule\per\mole\per\kelvin}} +% {J mol-1 K-1}% +% } +%\end{LaTeXdemo} +% +% \subsection{A left-aligned column visually centred under a heading} +% +% When you have a column of non-related numbers, the usual advice is to +% make these left-aligned and then centre the resulting column under the +% heading. With the \pkg{dcolumn} package, that would be done with +% something like |D{x}{}{5.0}|. This is something of an abuse of the +% nature of a number, but can also be done using \pkg{siunitx} +% (\ref{tbl:xmpl:unrel}). +%\begin{LaTeXdemo}[code and float] +% \begin{table} +% \caption{Formatting unrelated numbers} +% \label{tbl:xmpl:unrel} +% \centering +% \begin{tabular} +% { +% S[ +% table-format = 5.0, +% parse-numbers = false, +% input-symbols=., +% input-decimal-markers = x +% ] +% } +% \toprule +% \multicolumn{1}{c}{Header} \\ +% \midrule +% 120 \\ +% 12.3 \\ +% 12340 \\ +% 12.02 \\ +% 123 \\ +% 1 \\ +% \bottomrule +% \end{tabular} +% \end{table} +%\end{LaTeXdemo} +% +%\subsection{Symbols and \texorpdfstring{\XeTeX}{XeTeX}} +% +% A small number of non-Latin symbols are needed by \pkg{siunitx}, +% notably \SIUnitSymbolOhm\ and \SIUnitSymbolMicro. The package picks +% glyphs for these which are correct in the sense that they are upright +% (not italic) symbols, and match the \LaTeX{} standard Computer Modern +% font. However, this does not make them the best choice if other +% fonts are in use, which is particularly common when \XeTeX{} is +% being used. +% +% \XeTeX{} users will probably need to choose appropriate symbols +% themselves. The correct choice depends on the fonts in use, but many +% system fonts include Greek letters and other symbols (which is not +% the case with most \TeX-specific fonts). An appropriate setting +% could then be to use the text \SIUnitSymbolMicro\ symbol in all +% cases: +%^^A This document cannot be UTF-8, as it has to work correctly with +%^^A pdfLaTeX. So there is a bit of work to do here to get the right +%^^A output. +%\begin{flushleft} +% \ttfamily +% \textbackslash \textcolor{blue}{sisetup}\{\\ +% \ \ math-micro = \textbackslash +% \textcolor{blue}{text}\{\SIUnitSymbolMicro\}, \\ +% \ \ text-micro \ = \SIUnitSymbolMicro \\ +% \} +%\end{flushleft} +% It may also be desirable in these cases to select a fixed font +% using the \pkg{fontspec} package, for example +%\begin{LaTeXdemo}[code only] +% \sisetup{ +% math-micro = \fontspec{Minion Pro} \textmu, +% text-micro = \fontspec{Minion Pro} \textmu +% } +%\end{LaTeXdemo} +% +%\subsection{Scaled document fonts with \texorpdfstring{\XeTeX}{XeTeX}} +% +% The \pkg{fontspec} package makes it possible to scale the document +% body font. This can lead to unexpected problems with printing +% for \pkg{siunitx}, as some symbols will not scale while numbers +% and text will. The problem is best avoided by forcing \pkg{siunitx} +% to use the default math font for all output: +%\begin{LaTeXdemo}[code only] +% \sisetup{ +% mode = math, +% math-rm = \ensuremath +% } +%\end{LaTeXdemo} +% This will cause all \pkg{siunitx} output \emph{not} to scale at all, +% consistent with other mathematical content. +% +% \subsection{Interaction with \pkg{tex4ht}} +% +% \pkg{siunitx} will detect when \pkg{tex4ht} is in use, and makes +% some changes to the way output is printed. Text mode printing is +% automatically selected, and certain items (such as spaces) are +% printed in text mode rather than as math. This is designed to +% reduce the likelihood of spurious formulae appearing in, for +% example, output converted to OpenOffice format. +% +%\subsection{Maximising performance} +% +% Both the number and unit parsers require significant effort in +% terms of \TeX{} programming. For input that does not require +% such processing, the maximum performance for \pkg{siunitx} can +% therefore be obtained by turning off both systems: +%\begin{LaTeXdemo} +% \SI{7.3}{\Hz} \\ +% \SI[parse-units = false]{7.3}{\Hz} \\ +% \SI[ +% parse-numbers = false, +% parse-units = false +% ]{7.3}{\Hz} +%\end{LaTeXdemo} +% +%\subsection{Transferring settings to \pkg{pgf}} +% +%\DescribeMacro{\SendSettingsToPgf} +%\changes{v2.0a}{2010/05/28}{Make \cs{SendSettingsToPgf} available +% in document body} +% The numerical engine in the \pkg{pgf} package has settings similar +% to those in \pkg{siunitx}. To enable working with both packages +% easily, the macro \cs{SendSettingsToPgf} is available. It will +% set some commonly-used numerical formatting options in \pkg{pgf} +% to the current values used by \pkg{siunitx} to make using the +% two packages together more convenient for end users. This +% function can be used at any point after loading both the +% \pkg{pgf} and \pkg{siunitx} packages. +%\begin{LaTeXdemo}[code only] +% \documentclass{article} +% \usepackage{pgf,siunitx} +% \sisetup{...} +% \SendSettingsToPgf +% ... +%\end{LaTeXdemo} +% +%\subsection{Using \pkg{siunitx} with the \pkg{cellspace} package} +% +% Both \pkg{siunitx} and \pkg{cellspace} use the letter \texttt{S} for a +% new column type as standard. If \pkg{cellspace} loaded and is using the +% \texttt{S} column specifier, \pkg{siunitx} will move the +% functionality of \pkg{cellspace} to the letter \texttt{C}, and \texttt{S} +% will be used by \pkg{siunitx}. This +% allows the normal use of \pkg{cellspace} with standard column types: +% it does \emph{not} work with the \pkg{siunitx} \texttt{S} or +% \texttt{s} columns. Note that \pkg{cellspace} can be loaded with a +% user-selectable identifier, for example +%\begin{LaTeXdemo}[code only] +% \usepackage[column=Q]{cellspace} +%\end{LaTeXdemo} +% +%\subsection{Special considerations for the \cs{kWh} unit} +% +% The \file{abbreviations} configuration file provides the unit +% \cs{kWh}, which is set up with no spacing between the +% \enquote{\si{\kilo\watt}} and the \enquote{\si{\hour}} unit to +% give \enquote{\si{\kWh}}. However, this only applies when the unit +% is given on its own: combinations will follow the normal rules +%\begin{LaTeXdemo} +% \si{\kWh} \\ +% \si{\kWh\per\metre} +%\end{LaTeXdemo} +% This is because the unit \cs{kWh} is defined so that it can still be +% varied by altering \cs{kilo}, \cs{watt} and \cs{hour}, and so that +% the prefix can still be turned into a number. However, some users +% may prefer to have a non-flexible macro which never adds a space. +% This can be achieved by redefining \cs{kWh} with \cs{DeclareSIUnit}, +% by added an alternative definition +%\begin{LaTeXdemo}[code only] +% \DeclareSIUnit\kWh{kWh} +% \DeclareSIUnit\KWH{kWh} +%\end{LaTeXdemo} +% or of course by using literal unit input. +%\begin{LaTeXdemo} +% \si{\KWH\per\metre}\\ +% \si{kWh.m^{-1}} +%\end{LaTeXdemo} +% +% Another point to notice is that the \cs{per} macro applies to +% the next unit, and not an entire unit combination. Thus in +%\begin{LaTeXdemo} +% \si{\candela\per\kWh} +%\end{LaTeXdemo} +% \cs{per} applies to the watts but not to the hours. In this case, +% the units need to be written out in full or the \opt{sticky-per} +% option should be used. +%\begin{LaTeXdemo} +% \si{\candela\per\kilo\watt\per\hour} \\ +% \si[sticky-per]{\candela\per\kWh} +%\end{LaTeXdemo} +% +%\subsection{Adding items after the last column of a tabular} +%\changes{v2.0d}{2010/06/10}{Document special case situations for last +% cell in table row} +% +% When using the \pkg{array} package \enquote{\texttt{<}} construct +% to insert material after an \texttt{S} or \texttt{s} column, the +% alignment of the final column may be wrong if the standard tabular row +% terminator |\\| is used. +% This is due to the way that \LaTeX{} constructs +% tables at a low level. The incorrect spacing can be avoided by using +% the \TeX{} \cs{cr} primitive to end the table rows (\cref{tab:cr}). +%\begin{LaTeXdemo}[code and float] +% \begin{table} +% \caption{Correcting spacing in last \texttt{S} column} +% \label{tab:cr} +% \hfil +% \begin{tabular}{S<{\,\si{\kg}}S<{\,\si{\kg}}} +% \toprule +% \multicolumn{1}{c}{Long header} & +% \multicolumn{1}{c}{Long header} \\ +% \midrule +% 1.23 & 1.23 \\ +% 4.56 & 4.56 \\ +% 7.8 & 7.8 \\ +% \bottomrule +% \end{tabular} +% \hfil +% \begin{tabular}{S<{\,\si{\kg}}S<{\,\si{\kg}}} +% \toprule +% \multicolumn{1}{c}{Long header} & +% \multicolumn{1}{c}{Long header} \\ +% \midrule +% 1.23 & 1.23 \cr +% 4.56 & 4.56 \cr +% 7.8 & 7.8 \cr +% \bottomrule +% \end{tabular} +% \hfil +% \end{table} +%\end{LaTeXdemo} +% +%\subsection{Creating a column with numbers and units} +% +% Usually, numbers in a table should be given with the units in the +% column heading. However, there are cases where a series of data are +% best presented in a table but have different units. There are two +% ways to do this (\cref{tab:xmpl:mixed}). The first is to place the +% units in the first column of the table, which makes sense if there +% are several related items in the table. The second method is to +% generate two columns, one for numbers and a second for units, and then +% to format these to give the visual effect of a single column. The +% later effect is most appropriate when only one set of numbers are +% presented in a table. +%\begin{LaTeXdemo}[code and float] +% \begin{table} +% \caption{Tables where numbers have different units} +% \label{tab:xmpl:mixed} +% \hfil +% \begin{tabular} +% { +% >{$}l<{$} +% S[table-format = 2.3(1)] +% S[table-format = 3.3(1)] +% } +% \toprule +% & {One} & {Two} \\ +% \midrule +% a / \si{\angstrom} & 1.234(2) & 5.678(4) \\ +% \beta / \si{\degree} & 90.34(4) & 104.45(5) \\ +% \mu / \si{\per\mm} & 0.532 & 0.894 \\ +% \bottomrule +% \end{tabular} +% \hfil +% \begin{tabular} +% {S[table-format=1.3]@{\,}s[table-unit-alignment = left]} +% \toprule +% \multicolumn{2}{c}{Heading} \\ +% \midrule +% 1.234 & \metre \\ +% 0.835 & \candela \\ +% 4.23 & \joule\per\mole \\ +% \bottomrule +% \end{tabular} +% \hfil +% \end{table} +%\end{LaTeXdemo} +% +%\subsection{Tables with heading rows} +%\changes{v2.0s}{2010/08/12}{Document how to do mixed bold and normal +% numbers in tables} +% +% A common format for tables is to make the heading row visually +% distinct using a background colour and bold text. If numbers appear +% in such a heading row within an \texttt{S} column then getting the +% appearance right can be challenging. The best approach is to +% make the \cs{bfseries} macro \enquote{robust} (as demonstrated in +% \cref{sec:expanding}), then to use this macro to make the heading +% cells bold. This approach is illustrated in \cref{tab:xmpl:headers}, +% along with the use of \cs{rowcolor} to provide a background colour. +%\begin{LaTeXdemo}[code and float] +% \begin{table} +% \caption{Header row in a table} +% \label{tab:xmpl:headers} +% \robustify\bfseries +% \centering +% \begin{tabular} +% {S[detect-weight,table-format = 3.3]} +% \rowcolor[gray]{0.9} +% \bfseries 123.456 \\ +% 23.45 \\ +% 123.4 \\ +% 3.456 \\ +% \end{tabular} +% \end{table} +%\end{LaTeXdemo} +% +%\subsection{Associating a locale with a \pkg{babel} language} +% +% It is possible to instruct the \pkg{babel} package to switch +% to a particular \pkg{siunitx} locale when changing language. This +% can be done using the \pkg{babel} \cs{extras\meta{language}} +% system. For example, to associate the \texttt{DE} locale with +% the \texttt{german} \pkg{babel} language, the appropriate +% code would be +%\begin{LaTeXdemo}[code only] +% \addto\extrasgerman{\sisetup{locale = DE}} +%\end{LaTeXdemo} +% +%\section{Information for those upgrading} +% +%\subsection{Upgrading from version 1} +%\changes{v2.0a}{2010/05/28}{Fix various errors in \file{version-1} +% configuration file} +%\changes{v2.0a}{2010/05/28}{Detect use of version 1 options and +% automatically load appropriate configuration file} +%\changes{v2.0a}{2010/05/28}{Include high energy physics units in +% discussion of old configurations and in \file{version-1} +% configuration file} +%\changes{v2.0b}{2010/06/01}{Further improvements to \file{version-1} +% configuration file} +%\changes{v2.0r}{2010/08/02}{Error in definition for old +% \opt{decimalsymbol} option corrected} +%\changes{v2.1d}{2010/11/14}{Error with definition of version 1 option +% \opt{xspace} corrected} +% +% The key--value control system of \pkg{siunitx} has been completely +% rewritten for version 2, and at the same time some of the macros +% provided by the package have been renamed and reworked. The package +% can be loaded with a configuration file to provide most of the +% same options and defaults as in version 1: +%\begin{LaTeXdemo}[code only] +% \usepackage[version-1-compatibility]{siunitx} +%\end{LaTeXdemo} +% Many of the options from version 1 map to similar ones in version 2 +% (\cref{tab:opt:map}). The correspondence often includes a syntax +% change: consult details of the new options for the correct syntax for +% the new options. In some cases, the new approach is different to the +% older one, and in these cases the most appropriate option new has been +% listed in the table. +%\begin{center} +% \tablecaption{Mapping of version 1 options to version 2.} +% \label{tab:opt:map} +% \tablefirsthead{^^A +% \toprule +% \multicolumn{1}{l}{Version 1} & +% \multicolumn{1}{l}{See in version 2} \\ +% \midrule +% } +% \tablehead{^^A +% \multicolumn{2}{l}{\emph{Continued from previous page}} \\ +% \toprule +% \multicolumn{1}{l}{Version 1} & +% \multicolumn{1}{l}{See in version 2} \\ +% \midrule +% } +% \tabletail{^^A +% \bottomrule +% \multicolumn{2}{r}{\emph{Continued on next page}} \\ +% } +% \tablelasttail{\bottomrule} +% +% \begin{xtabular}{>{\ttfamily}l>{\ttfamily}l} +% addsign & explicit-sign \\ +% allowlitunits & free-standing-units \\ +% allowoptarg & unit-optional-argument \\ +% allowzeroexp & retain-zero-exponent \\ +% anglesep & arc-separator \\ +% astroang & angle-symbol-over-decimal \\ +% closeerr & close-bracket \\ +% closefrac & close-bracket \\ +% closerange & close-bracket \\ +% colour & color \\ +% colorall & color \\ +% colourall & color \\ +% colorunits & unit-color \\ +% colorneg & negative-color \\ +% colourneg & negative-color \\ +% colourunits & unit-color \\ +% colorvalues & number-color \\ +% colourvalues & number-color \\ +% decimalsymbol & output-decimal-marker \\ +% detectdisplay & detect-display-math \\ +% digitsep & group-separator \\ +% dp & round-mode \\ +% & round-precision \\ +% errspace & uncertainty-separator \\ +% expbase & exponent-base \\ +% expproduct & exponent-product \\ +% fixdp & round-mode \\ +% fixsf & round-mode \\ +% fraction & fraction-function \\ +% inlinebold & detect-inline-weight \\ +% locale & locale \\ +% mathOmega & math-ohm \\ +% mathcelsius & math-celsius \\ +% mathdegree & math-degree \\ +% mathminute & math-arcminute \\ +% mathmu & math-micro \\ +% mathringA & math-angstrom \\ +% mathrm & math-rm \\ +% mathsOmega & math-ohm \\ +% mathscelsius & math-celsius \\ +% mathsdegree & math-degree \\ +% mathsecond & math-arcsecond \\ +% mathsf & math-sf \\ +% mathsminute & math-arcminute \\ +% mathsmu & math-micro \\ +% mathsringA & math-angstrom \\ +% mathsrm & math-rm \\ +% mathssecond & math-arcsecond \\ +% mathssf & math-sf \\ +% mathstt & math-tt \\ +% mathtt & math-tt \\ +% mode & mode \\ +% negcolor & negative-color \\ +% negcolour & negative-color \\ +% numaddn & input-symbols \\ +% numcloseerr & input-close-uncertainty \\ +% numdecimal & input-decimal-markers \\ +% numdigits & input-digits \\ +% numdiv & input-quotient \\ +% numexp & input-exponent-markers \\ +% numgobble & input-ignore \\ +% numopenerr & input-open-uncertainty \\ +% numprod & input-product \\ +% numsign & input-signs \\ +% obeyall & detect-all \\ +% obeybold & detect-weight \\ +% obeyfamily & detect-family \\ +% obeyitalic & detect-shape \\ +% obeymode & detect-mode \\ +% openerr & open-bracket \\ +% openfrac & open-bracket \\ +% openrange & open-bracket \\ +% padangle & add-arc-degree-zero \\ +% & add-arc-minute-zero \\ +% & add-arc-second-zero \\ +% padnumber & add-decimal-zero \\ +% & add-integer-zero \\ +% per & per-mode \\ +% prefixsymbolic & prefixes-as-symbols \\ +% prespace & space-before-unit \\ +% redefsymbols & redefine-symbols \\ +% repeatunits & multi-part-units \\ +% & product-units \\ +% & range-units \\ +% retainplus & retain-explicit-plus \\ +% seperr & separate-uncertainty \\ +% sepfour & group-four-digits \\ +% sf & round-mode \\ +% & round-precision \\ +% sign & explicit-sign \\ +% slash & per-symbol \\ +% stickyper & sticky-per \\ +% strict & strict \\ +% tabalign & table-alignment \\ +% tabalignexp & table-align-exponent \\ +% tabautofit & table-auto-round \\ +% tabformat & table-format \\ +% tabnumalign & table-number-alignment \\ +% tabparseonly & table-parse-only \\ +% tabexpalign & table-align-exponent \\ +% tabtextalign & table-text-alignment \\ +% tabunitalign & table-unit-alignment \\ +% textcelsius & text-celsius \\ +% textdegree & text-degree \\ +% textminute & text-arcminute \\ +% textmode & mode \\ +% textmu & text-micro \\ +% textOmega & text-ohm \\ +% textringA & text-angstrom \\ +% textrm & text-rm \\ +% textsecond & text-arcsecond \\ +% textsf & text-sf \\ +% texttt & text-tt \\ +% tightpm & tight-spacing \\ +% tophrase & range-phrase \\ +% trapambigerr & multi-part-units \\ +% trapambigfrac & bracket-numbers \\ +% trapambigrange & range-units \\ +% unitcolor & unit-color \\ +% unitcolour & unit-color \\ +% unitmathrm & unit-math-rm \\ +% unitmathsf & unit-math-sf \\ +% unitmathsrm & unit-math-rm \\ +% unitmathssf & unit-math-sf \\ +% unitmathstt & unit-math-tt \\ +% unitmathtt & unit-math-tt \\ +% unitmode & unit-mode \\ +% unitsep & inter-unit-product \\ +% unitspace & inter-unit-product \\ +% valuecolor & number-color \\ +% valuecolour & number-color \\ +% valuemathrm & number-math-rm \\ +% valuemathsf & number-math-sf \\ +% valuemathsrm & number-math-rm \\ +% valuemathssf & number-math-sf \\ +% valuemathstt & number-math-tt \\ +% valuemathtt & number-math-tt \\ +% valuemode & value-mode \\ +% valuesep & number-unit-product \\ +% xspace & use-xspace \\ +% \end{xtabular} +%\end{center} +% A small number of the options from version 1 are used unchanged in +% version 2, for example the \opt{mode} setting. These are listed above +% but require no action on the part of the user. There are also a +% few options which are no longer used at all, and are therefore ignored +% by the current code. +% +% Loading configuration files has been completely changed, and this +% means that the options \opt{alsoload}, \opt{load} and \opt{noload} are +% ignored by version 2. In the same way the options \opt{debug} and +% \opt{log} are not used by the current release of \pkg{siunitx}, as +% this information is usually only needed by the package author. +% Emulation of older packages is no longer offered (it was intended +% to help with the transition form earlier packages), and so the +% \opt{emulate} option no longer applies. +% +%\subsection{Upgrading from version 2.0 or 2.1} +% +% User feedback on \pkg{siunitx} means that over time some renaming +% takes place. The following functions and options have been deprecated +% in version 2.2. They are therefore available in version 2.2, but +% should be replaced in new or updated documents with the successor +% names. +% +%\DescribeOption{angle-unit-separator} +%\DescribeOption{inter-unit-separator} +%\DescribeOption{number-unit-separator} +%\changes{v2.2}{2011/03/20}{Renamed \opt{angle-unit-separator} option +% to \opt{angle-unit-product}} +%\changes{v2.2}{2011/03/20}{Renamed \opt{inter-unit-separator} option +% to \opt{inter-unit-product}} +%\changes{v2.2}{2011/03/20}{Renamed \opt{number-unit-separator} option +% to \opt{number-unit-product}} +% These options have been replaced by the options +%\begin{itemize} +% \item \opt{angle-unit-product} +% \item \opt{inter-unit-product} +% \item \opt{number-unit-product} +%\end{itemize} +% as these items are formally products, and the new option names +% emphasise this. +% +%\DescribeMacro{\DeclareSIUnitWithOptions} +%\changes{v2.2}{2011/04/01}{Depreciate \cs{DeclareSIUnitWithOptions}} +% The \cs{DeclareSIUnit} function has been extended to take a +% first optional argument, which removes the need for +% \cs{DeclareSIUnitWithOptions}. This function is therefore depreciated +% but retained for compatibility. +% +% \subsection{Upgrading from version 2.2} +% +% \DescribeOption{load-configurations} +% \changes{v2.3}{2011/03/20}{Load abbreviations as standard} +% \changes{v2.3}{2011/03/20}{Replace \opt{load-configurations} option +% with separate \opt{abbreviations}, \opt{binary-units} and +% \opt{version-1-compatibility} options} +% The option \opt{load-configurations} has been deprecated in favour of the +% three options \opt{abbreviations}, \opt{binary-units} and +% \opt{version-1-compatibility}. At the same time, loading of the abbreviations +% is now the standard behaviour, and so in most cases no +% explicit configuration file loading will be needed. +% +% \DescribeOption{group-decimal-digits} +% \DescribeOption{group-integer-digits} +% The digit grouping options have been revised, and the options +% \opt{group-decimal-digits} and \opt{group-integer-digits} are now +% integrated into \opt{group-digits}. +% \DescribeOption{group-four-digits} +% At the same time, the \opt{group-four-digits} option has been extended +% to the new option \opt{group-minimum-digits}. +% +% \DescribeOption{literal-superscript-as-power} +% The new {literal-superscript-as-power} option means that the standard +% behaviour now uses the current math font for superscripts, even when +% units are printed literally. This will only be obvious in documents such +% as this manual, where the text and math mode numerals are (deliberately) +% different. To restore the previous behaviour, set +% \opt{literal-superscript-as-power = false}. +% +% \subsection{Upgrading from version 2.3} +% +% The number of options which assume that the input is given in math mode +% has been significantly reduced. As most material can be typeset in either +% math or text mode, the \enquote{intrinsic} math mode options could lead to +% inconsistent output. The only options which now force math mode are those +% for products, which will almost always require the use of math mode. +% +% \subsection{Upgrading from version 2.4} +% +% The process of removing options which assume math mode, begun with +% version~2.4, has been taken further, and only \opt{output-product} +% and \opt{exponent-product} now do not require \cs{ensuremath} for material +% which must be in math mode. The standard settings have been altered to take +% account of this, but user-set options for products may need to be updated +% accordingly. +% +% \subsection{Upgrading from version 2.5} +% +% All printing now takes place in math mode (\emph{i.e.}~\opt{mode = math} +% is set). This may alter the appearance of some units, and users may want +% to verify the output is correct. +% +%\section{Correct application of (SI) units} +% +% Consistent and logical units are a necessity for scientific work, +% and have applicability everywhere. Historically, a number of +% systems have been used for physical units. SI units were +% introduced by the \emph{Conf{\'e}rence G{\'e}n{\'e}rale des Poids et +% Mesures} (CGPM) in 1960. SI units are a coherent system based on +% seven base units, from which all other units may be derived. +% +% At the same time, physical quantities with units are mathematical +% entities, and as such way that they are typeset is important. In +% mathematics, changes of type (such as using bold, italic, sans +% serif typeface and so on) convey information. This means that +% rules exist not only for the type of units to be used under the SI +% system, but also the way they should appear in print. Advice on +% best practice has been made available by the \emph{National +% Institute of Standards and Technology} (NIST) \cite{NIST}. +% +% As befits an agreed international standard, the full rules are +% detailed. It is not appropriate to reproduce these in totality +% here; instead, a useful summary of the key points is provided. The +% full details are available from the \emph{Bureau International des +% Poids et Mesures} \cite{BIPM}. +% +% \pkg{siunitx} takes account of the information given here, so far as +% is possible. Thus the package defaults follow the recommendations +% made for typesetting numbers and units. Spacing and so forth is +% handled in such a way as to make implementing the rules +% (relatively) easy. +% +%\subsection{Units} +% +% There are seven base SI units, listed in \cref{tab:unit:base}. +% Apart from the kilogram, these are defined in terms of a measurable +% physical quantity needing the definition alone.\footnote{Some base +% units need others defined first; there is therefore a required +% order of definition.} The base units have been chosen such that +% all physical quantities can be expressed using an appropriative +% combination of these units, needing no others and with no +% redundancy. The kilogram is slightly different from the other base +% units as it is still defined in terms of a \enquote{prototype} held in +% Paris. +% +% All other units within the SI system are regarded as \enquote{derived} +% from the seven base units. At the most basic, all other SI units +% can be expressed as combinations of the base units. However, many +% units (listed in \cref{tab:unit:derived,tab:unit:accepted}) have a +% special name and symbol. Most of these units are simple combinations +% of one or more base units (raised to powers as appropriate). A small +% number of units derived from experimental data are allowed as SI +% units (\cref{tab:unit:physical}). +% +% A series of SI prefixes for decimal multiples and sub-multiples are +% provided, and can be used as modifiers for any SI unit (either base +% or derived units) with the exception of the kilogram. The prefixes +% are listed in \cref{tab:unit:prefix}. No space should be used +% between a prefix and the unit, and only a single prefix should be +% used. Even the degree Celsius can be given a prefix, for example +% \SI{1}{\milli\degreeCelsius}. +% +% It is important to note that the kilogram is the only SI unit with +% a prefix as part of its name and symbol. Only single prefix may +% be used, and so in the case of the kilogram prefix names are used +% with the unit name \enquote{gram} and the prefix symbols are used with +% the unit symbol \si{\gram}. For example +% \( \SI[prefixes-as-symbols = false]{1}{\milli\gram} = +% \SI{1}{\milli\gram} \). +% +% The application of SI units is meant to provide a single set of +% units which ensure consistency and clarity across all areas. +% However, other units are common is many areas, and are not without +% merit. The units provided by \pkg{siunitx} by default do not include +% any of these; only units which are part of the SI set or are +% accepted for use with SI units are defined. However, several other +% sets of units can be loaded as optional modules. The binary +% prefixes and units (\cref{tab:unit:binary}) are the most obvious +% example. These are \emph{not} part of the SI specifications, but the +% prefix names are derived from those in \cref{tab:unit:prefix}. +% +% Other units are normally to be avoided where possible. SI units +% should, in the main, be preferred due to the advantages of clear +% definition and self-consistency this brings. However, there will +% probably always be a place for specialist or non-standard units. +% This is particularly true of units derived from basic physical +% constants. +% +% There are also many areas where non-standard units are used so +% commonly that to do otherwise is difficult or impossible. For +% example, most synthetic chemists measure the pressure inside vacuum +% apparatus in \si{\mmHg}, partly because the most common gauge for +% the task still uses a column of mercury metal. For these reasons, +% \pkg{siunitx} does define non-SI units. +% +%\subsection{Mathematical meaning} +% +% As explained earlier, a number--unit combination is a single +% mathematical entity. This has implications for how both the number +% and the unit should be printed. Firstly, the two parts should not +% be separated: a quantity is a product of the number and the unit. +% With the exception of the symbols for plane angles (\si{\degree}, +% \si{\arcminute} and \si{\arcsecond}), the \textsc{bipm} +% specifies either a space or half-height (centred) dot should be +% used \cite{BIPM}. +%\begin{LaTeXdemo} +% A space for \SI{10}{\percent}\\ +% and also for \SI{100}{\degreeCelsius}\\ +% but not for \ang{1.23}. +%\end{LaTeXdemo} +% +% The mathematical meaning of units also means that the shape, weight +% and family are important. Units are supposed to be typeset in an +% upright, medium weight font. Italic, bold and sans serif are +% all used mathematically to convey other meanings. (In an all +% sans serif document, using sans serif for units is reasonable.) +% The \pkg{siunitx} +% package defaults again follow this convention: any local settings are +% ignored, and uses the current upright math font. However, +% there are occasions where this may not be the most desirable +% behaviour. A classic example would be in an all-bold section +% heading. As the surrounding text is bold, some people feel that +% any units should follow this. +%\begin{LaTeXdemo} +% Units should \textbf{not be bold: \SI{54}{\farad}}\\ +% \textbf{But perhaps in a running block,\\ +% it might look better: \SI[detect-weight]{54}{\farad}} +%\end{LaTeXdemo} +% +% Symbols for units formed from other units by multiplication are +% indicated by means of either a half-height (that is, centred) dot +% or a (thin) space. +%\begin{LaTeXdemo} +% \( \si{\metre\second} = \text{metre second} \) \\ +% \( \si{\milli\second} = \text{millisecond} \) \\ +% \sisetup{inter-unit-product = \ensuremath { { } \cdot { } } } +% \( \si{\metre\second} = \text{metre second} \) \\ +% \( \si{\milli\second} = \text{millisecond} \) +%\end{LaTeXdemo} +% There are some circumstances under which it is common practice to omit +% any spaces. The classic example is \si{\kWh}, where +% \enquote{\si[inter-unit-product = \,]{\kWh}} does not add any +% useful information. If using such a unit repeatedly, users of +% \pkg{siunitx} are advised to create a custom unit to ensure +% consistency. It is important to note that while this is common +% practice, it is \emph{not} allowed by the \textsc{bipm} +% \cite{BIPM}. +% +% Symbols for units formed from other units by division are indicated +% by means of a virgule (oblique stroke, slash, "/"), a horizontal +% line, or negative exponents.\footnote{Notice that a virgule and a +% solidus are not the same symbol.} However, to avoid ambiguity, the +% virgule must not be repeated on the same line unless parentheses +% are used. This is ensured when using named unit macros in +% \pkg{siunitx}, which will \enquote{trap} repeated division and format +% it correctly. In complicated cases, negative exponents are to be +% preferred over other formats. +%\begin{LaTeXdemo} +% \si{\joule\per\mole\per\kelvin}\\ +% \si[per-mode = fraction]{\joule\per\mole\per\kelvin}\\ +% \si[per-mode = symbol]{\joule\per\mole\per\kelvin} +%\end{LaTeXdemo} +% +% Products and errors should show what unit applies to each number +% given. Thus \SI[product-units = brackets]{2x3}{\metre} is an +% ordered set of lengths of a geometric area, whereas +% \SI[product-units = single]{2x3}{\metre} is a length (and equal +% to \SI{6}{\metre}). Thus, \(\times\) is not a product but is a +% mathematical operator; in the same way, a \(2 \times 3\) matrix is not +% a \(6\) matrix! In some areas, areas and volumes are given with +% separated units but a unit raised to the appropriate power: +% \SI[product-units = power]{2 x 3}{\metre}. Although this does +% display the correct overall units, it is potentially-confusing and is +% not encouraged. +% +% Care must be taken when writing ranges of numbers. For purely +% numerical values, it is common to use a en-dash to show a range, for +% example \enquote{see pages 1--5}. On the other hand, physical +% quantities could be misinterpret as negative values if written in this +% way. As the unit--number combination is a single mathematical entity, +% writing the values with an en-dash followed by a single unit is also +% incorrect. As a result, using the word \enquote{to} is strongly +% recommended. +%\begin{LaTeXdemo} +% \SIrange{1}{5}{\metre} long. +%\end{LaTeXdemo} +% +%\subsection{Graphs and tables} +% +% In graphs and tables, repetition of the units following each entry +% or axis mark is confusing and repetitive. It is therefore best to +% place the unit in the label part of the information. Placing the +% unit in square brackets is common but mathematically +% poor.\footnote{For example, for an acceleration \(a\), the expression +% \([a]\) is the dimensions of \(a\), \emph{i.e.}~length per time +% squared in this case.} Much better is to show division of all +% quantities by the unit, which leaves the entries as unitless ratios. +% This is illustrated in \cref{tab:xmpl:unitless} and +% \cref{fig:xmpl:unitless}. +%\begin{LaTeXdemo}[code and float] +% \begin{table} +% \centering +% \caption{An example of table labelling.} +% \label{tab:xmpl:unitless} +% \sisetup{ +% table-number-alignment = center, +% table-figures-integer = 1, +% table-figures-decimal = 4 +% } +% \begin{tabular}{cS} +% \toprule +% Entry & {Length/\si{\metre}} \\ +% \midrule +% 1 & 1.1234 \\ +% 2 & 1.1425 \\ +% 3 & 1.7578 \\ +% 4 & 1.9560 \\ +% \bottomrule +% \end{tabular} +% \end{table} +%\end{LaTeXdemo} +%\begin{LaTeXdemo}[code and float] +% \begin{figure} +% \centering +% \begin{tikzpicture} +% \begin{axis}[ +% xlabel = \( t/\si{\second} \), +% xmax = 6, +% xmin = 0, +% ylabel = \( d/\si{\metre} \), +% ymin = 0 +% ] +% \addplot[smooth,mark=*] +% plot coordinates { +% (0,0) +% (1,5) +% (2,8) +% (3,9) +% (4,8) +% (5,5) +% (6,0) +% }; +% \end{axis} +% \end{tikzpicture} +% \caption{An example of graph labelling.} +% \label{fig:xmpl:unitless} +% \end{figure} +%\end{LaTeXdemo} +% +% In most cases, adding exponent values in the body of a table is +% less desirable than adding a fixed exponent to column headers. An +% example is shown in \cref{tab:good}. The use of \cs{multicolumn} is +% needed here due to the \enquote{\texttt{<}}; without \cs{multicolumn}, +% the titles are followed by \enquote{\si{\kilo\gram}}! +%\begin{LaTeXdemo}[code and float] +% \begin{table} +% \centering +% \caption{Good and bad columns.} +% \label{tab:good} +% \sisetup{table-number-alignment = center} +% \begin{tabular}{ +% c +% S[ +% table-figures-integer = 1, +% table-figures-decimal = 3, +% table-figures-exponent = 1 +% ] +% @{\,\si{\kilogram}} +% S[ +% table-figures-integer = 2, +% table-figures-decimal = 2 +% ] +% } +% \toprule +% Entry & \multicolumn{1}{c}{Mass} & +% {Mass/\SI{e3}{\kilogram}} \\ +% \midrule +% 1 & 4.56e3 & 4.56 \\ +% 2 & 2.40e3 & 2.40 \\ +% 3 & 1.345e4 & 13.45 \\ +% 4 & 4.5e2 & 0.45 \\ +% \bottomrule +% \end{tabular} +% \end{table} +%\end{LaTeXdemo} +% +%\section{Making suggestions and reporting bugs} +% +% Feedback on \pkg{siunitx} is always welcome, either to make +% suggestions or to report problems. When sending feedback, it is +% always useful if a small example file is included, showing the +% bug being reported or illustrating the desired output. It is +% helpful if a \enquote{reference rendering} is included, showing what +% the output should look like. A typical example file might read +%\begin{LaTeXdemo}[code only] +% \listfiles +% % Use the article class unless the problem is class-dependent +% \documentclass{article} +% \usepackage{siunitx} +% % Other packages loaded as required +% \begin{document} +% Reference output: $ 1.23\,\mathrm{m} $ +% +% siunitx output: \SI{1.23}{\metre} +% \end{document} +%\end{LaTeXdemo} +% As illustrated, it is usually best to use the \texttt{article} +% class and to only load packages which are needed to show the issue. +% It is also useful to include a copy of the log file generate by +% \TeX{} when reporting a bug (as the versions of packages can be +% important to solving the issue). +% +% Feedback can be sent in a range of ways. The development code +% is hosted by +% \href{https://github.com/josephwright/siunitx/}{GitHub}, +% and the site includes an issue tracker. Adding feedback directly +% to the database means that other users can see it, and also +% ensures that it does not get forgotten. E-mailing directly +% will also definitely get attention: +% \href{mailto:joseph.wright@morningstar2.co.uk} +% {\texttt{joseph.wright@morningstar2.co.uk}}. +% +% \section{Code level interfaces} +% +% At present, most interfaces in \pkg{siunitx} at the code level are internal. +% This largely reflects the parallel between \pkg{siunitx} and core \pkg{expl3} +% development: much of the code here was written whilst the \LaTeX{} team were +% defining how best to handle this area. Development work on the next major +% release of \pkg{siunitx} includes a full set of documented code level +% interfaces. Some of these will be added to this (release) version of the +% package over time, where this is appropriate. +% +% \begin{variable}{\l_siunitx_unit_symbolic_seq} +% This sequence contains all of the symbolic \meta{unit} names defined: +% these will be in the form of control sequences such as |\kilogram|. +% The order of the sequence is unimportant. +% \end{variable} +% +%\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} {2018/05/17} {2.7s} + {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 } { 2015/11/15 } + { } + { + \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} +% +% Add some variants. +% \begin{macrocode} +\cs_generate_variant:Nn \clist_map_function:nN { nc } +\cs_generate_variant:Nn \tl_if_blank:nTF { V } +\cs_generate_variant:Nn \tl_replace_all:Nnn { No, NV , Nx } +% \end{macrocode} +% +%\begin{macro}{ +% \l_@@_tmp_bool , +% \l_@@_tmp_box , +% \l_@@_tmp_dim , +% \l_@@_tmp_int , +% \l_@@_tmpa_tl , +% \l_@@_tmpb_tl +%} +% Scratch variables. +% \begin{macrocode} +\bool_new:N \l_@@_tmp_bool +\box_new:N \l_@@_tmp_box +\dim_new:N \l_@@_tmp_dim +\int_new:N \l_@@_tmp_int +\tl_new:N \l_@@_tmpa_tl +\tl_new:N \l_@@_tmpb_tl +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{ +% \@@_error:nxx , +% \@@_error:nx , +% \@@_error:n +%} +%\begin{macro}{\l_@@_error_bool} +% General-purpose functions for throwing errors. +% \begin{macrocode} +\cs_new_protected:Npn \@@_error:nxx #1#2#3 { + \bool_set_true:N \l_@@_error_bool + \msg_error:nnxx { siunitx } {#1} {#2} {#3} +} +\cs_new_protected:Npn \@@_error:nx #1#2 { + \@@_error:nxx {#1} {#2} { } +} +\cs_new_protected:Npn \@@_error:n #1 { + \@@_error:nxx {#1} { } { } +} +\bool_new:N \l_@@_error_bool +% \end{macrocode} +%\end{macro} +%\end{macro} +% +% 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 unless there's a good reason +% to suspect +% \begin{macrocode} +\DeclareTextSymbolDefault \c_@@_minus_tl { TS1 } +\DeclareTextSymbol \c_@@_minus_tl { TS1 } { 61 } +\AtBeginDocument { + \@ifpackageloaded { fontspec } + { + \@ifpackageloaded { eulervm } + { } + { + \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}{\g_@@_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 \g_@@_omega_tl +\tl_gset:Nn \g_@@_omega_tl { \Omega } +\AtBeginDocument { + \cs_if_exist:NT \upOmega + { \tl_set:Nn \g_@@_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} +\exp_args:NNx \seq_const_from_clist:Nn \c_@@_old_options_seq + { + \tl_to_str:n + { + addsign , + allowlitunits , + allowoptarg , + allowzeroexp , + alsoload , + angformat , + anglesep , + astroang , + closeerr , + closrfrac , + closerange , + colour , + colorall , + colourall , + colorneg , + colourneg , + colourunits , + colourunits , + colorvalues , + colourvalues , + decimalsymbol , + debug , + detectdisplay , + digitsep , + dp , + emulate , + errspace , + eVcorra , + eVcorrb , + expbase , + expproduct , + fixdp , + fixsf , + fraction , + inlinebold , + loctolang , + log , + load , + mathOmega , + mathcelsius , + mathdegree , + mathminute , + mathmu , + mathringA , + mathrm , + mathsOmega , + mathscelsius , + mathsdegree , + mathsecond , + mathsf , + mathsminute , + mathsmu , + mathsringA , + mathsrm , + mathssecond , + mathssf , + mathstt , + mathtt , + negcolor , + negcolour , + noload , + numaddn , + numcloseerr , + numdecimal , + numdigits , + numdiv , + numexp , + numgobble , + numopenerr , + numprod , + numsign , + obeyall , + obeybold , + obeyfamily , + obeymode , + obeyitalic , + openerr , + openfrac , + openrange , + padangle , + padnumber , + per , + prefixbase , + prefixproduct , + prefixsymbolic , + prespace , + redefsymbols , + repeatunits , + retainplus , + seperr , + sepfour , + sf , + sign , + slash , + stickyper , + strictarc , + tabalign , + tabalignexp , + tabautofit , + tabexpalign , + tabformat , + tabnumalign , + tabparseonly , + tabtextalign , + textOmega , + textcelsius , + textdegree , + textminute , + textmode , + textmu , + textringA , + textrm , + textsecond , + textsf , + texttt , + tightpm , + tophrase , + trapamigerr , + trapambigfrac , + trapambigrange , + unitcolor , + unitcolour , + unitmathrm , + unitmathsf , + unitmathsrm , + unitmathssf , + unitmathstt , + unitmathtt , + unitmode , + unitsep , + unitspace , + valuecolor , + valuecolour , + valuemathrm , + valuemathsf , + valuemathsrm , + valuemathssf , + valuemathstt , + valuemathtt , + valuemode , + valuesep , + xspace + } + } +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\l_@@_key_tl} +% Unknown options should raise an \pkg{siunitx}-specific error message. +% \begin{macrocode} +\tl_new:N \l_@@_key_tl +\keys_define:nn { siunitx } { + unknown .code:n = + { + \seq_if_in:NVTF \c_@@_old_options_seq \l_keys_key_tl + { + \msg_warning:nnx { siunitx } { version-1-option } + { \exp_not:V \l_keys_key_tl } + \tl_set:Nx \l_@@_key_tl + { + \keys_set:nn { siunitx } + { + \exp_not:V \l_keys_key_tl + \tl_if_blank:nF {#1} { = \exp_not:n {#1} } + } + } + \keys_set:nn { siunitx } { version-1-compatibility } + \tl_use:N \l_@@_key_tl + } + { + \msg_error:nnx { siunitx } { unknown-option } + { \exp_not:V \l_keys_key_tl } + } + } +} +\AtBeginDocument { + \keys_define:nn { siunitx } { + unknown .code:n = + { + \seq_if_in:NVTF \c_@@_old_options_seq \l_keys_key_tl + { + \msg_error:nnx { siunitx } { version-1-option } + { \exp_not:V \l_keys_key_tl } + } + { + \msg_error:nnx { siunitx } { unknown-option } + { \exp_not:V \l_keys_key_tl } + } + } +} +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\@@_option_deactivate:n} +%\begin{macro}{\@@_option_deactivate_aux:n} +%\begin{macro}{\l_@@_option_deactivate_clist} +% Some options need to be deactivated at the start of the document. +% \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} +% +% Variants needed which are not in \pkg{expl3}. +% \begin{macrocode} +\cs_generate_variant:Nn \tl_if_empty_p:n { f } +\cs_generate_variant:Nn \tl_if_empty:nT { f } +\cs_generate_variant:Nn \tl_if_in:NnTF { NV } +\cs_generate_variant:Nn \tl_replace_all:Nnn { NnV } +% \end{macrocode} +% +% \begin{macro}[pTF]{\@@_cs_if_tl:N} +% A test for token lists (more or less). +% \begin{macrocode} +\prg_new_conditional:Npnn \@@_cs_if_tl:N #1 { T, F , TF , p } + { + \bool_lazy_and:nnTF + { + \tl_if_empty_p:f + { + \token_get_prefix_spec:N #1 + \token_get_arg_spec:N #1 + } + } + { \bool_not_p:n { \cs_if_exist_p:c { \cs_to_str:N #1 ~ } } } + { \prg_return_true: } + { \prg_return_false: } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[EXP] +% {\@@_number_if_zero:nTF, \@@_number_if_zero_p:n \@@_number_if_zero_p:V} +% \begin{macro}[EXP, aux]{\@@_number_if_zero_aux:n} +% A test for all of the input to a function being made up of zeros: +% needed to avoid overflowing \TeX{}'s integer range. +% \begin{macrocode} +\prg_new_conditional:Npnn \@@_number_if_zero:n #1 { p , TF } + { + \tl_map_function:nN {#1} \@@_number_if_zero_aux:n + \prg_return_true: + } +\cs_generate_variant:Nn \@@_number_if_zero_p:n { V } +\cs_new:Npn \@@_number_if_zero_aux:n #1 + { + \token_if_eq_charcode:NNF #1 0 + { \tl_map_break:n { \prg_return_false: \use_none:n } } + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% 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 } + { + \sys_if_engine_xetex:T + { \cs_set_protected:Npn \@@_ensure_ltr:n #1 { \LRE {#1} } } + } + { } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_textsuperscript:n} +% This function is set up here so that it can be redefined +% elsewhere as expandable. That is used in the bookmark system so +% that \pkg{hyperref} does not raise any unnecessary warnings. With +% \pkg{fontspec} loaded the kernel defintion for \cs{textsuperscript} +% may get altered so a private copy of the orignal code is used. (Yes, +% this really should be done like Con\TeX{}t +% \begin{macrocode} +\cs_new_protected:Npn \@@_textsuperscript:n #1 + { + \m@th + \ensuremath { ^ { \mbox { \fontsize \sf@size \z@ \selectfont #1 } } } + } +% \end{macrocode} +% \end{macro} +% +%\begin{macro}{\l_@@_display_math_bool} +% To test for display math, a flag is added to the start of every +% display environment. +% \begin{macrocode} +\bool_new:N \l_@@_display_math_bool +\tex_everydisplay:D \exp_after:wN + { + \tex_the:D \tex_everydisplay:D + \bool_set_true:N \l_@@_display_math_bool + } +% \end{macrocode} +%\end{macro} +% +% \begin{macro}[TF]{\prop_get:NVN} +% Missing from \pkg{expl3} at the moment. +% \begin{macrocode} +\cs_generate_variant:Nn \prop_get:NnNT { NV } +\cs_generate_variant:Nn \prop_get:NnNF { NV } +\cs_generate_variant:Nn \prop_get:NnNTF { NV } +% \end{macrocode} +% \end{macro} +% +%\subsection{Font detection} +% +% A number of controls and tests are needed to control the font used +% for output. The detection routines set up various functions which can +% then be used inside the \cs{text} macro from the \pkg{amstext} +% package. By carrying out the changes outside math mode, bold can +% reliably be applied to math output. +% +%\begin{macro}{\@@_set_math_fam:n} +%\begin{macro}{ +% \c_@@_mathsf_int , +% \c_@@_mathtt_int +%} +% The detection routine needs some basic data about the sans serif and +% monospaced fonts in use. This is collected up at the start of the +% document. The families used can change between here and the start of +% the document. This is run as a hook onto \cs{document}, rather than +% using \cs{AtBeginDocument} as it has to come after anything that +% \pkg{fontspec} does (nasty errors arise otherwise). +% \begin{macrocode} +\cs_new_protected:Npn \@@_set_math_fam:n #1 { + \group_begin: + \hbox_set:Nn \l_@@_tmp_box + { + \ensuremath + { + \use:c { math #1 } + { + \int_const:cn { c_@@_math #1 _int } { \fam } + } + } + } + \group_end: +} +\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_const:cx { c_@@_text #1 _tl } { \use:c { #1 default } } +} +\AtBeginDocument { + \@@_set_text_fam:n { sf } + \@@_set_text_fam:n { tt } +} +% \end{macrocode} +%\end{macro} +%\end{macro} +% +%\begin{macro}{\l_@@_detect_inline_weight_tl} +% Used by the keys, but needs to be created here. +% \begin{macrocode} +\tl_new:N \l_@@_detect_inline_weight_tl +% \end{macrocode} +%\end{macro} +% +% \begin{variable}{\l_@@_detect_inline_family_tl} +% This one is not generated by the keys system. +% \begin{macrocode} +\tl_new:N \l_@@_detect_inline_family_tl +% \end{macrocode} +% \end{variable} +% +%\begin{macro}{ +% \l_@@_detect_display_math_bool , +% \l_@@_detect_family_bool , +% \l_@@_detect_inline_family_tl , +% \l_@@_detect_shape_bool , +% \l_@@_detect_mode_bool , +% \l_@@_detect_weight_bool +%} +% Font detection is all about creating switches, with just a little +% gloss for \texttt{detect-all} and \texttt{detect-none}. +% \begin{macrocode} +\keys_define:nn { siunitx } { + detect-all .choice:, + detect-all .default:n = true, + detect-all / false .meta:n = + { + detect-family = false , + detect-mode = false , + detect-shape = false , + detect-weight = false , + }, + detect-all / true .meta:n = + { + detect-family = true , + detect-mode = true , + detect-shape = true , + detect-weight = true , + }, + detect-display-math .bool_set:N = + \l_@@_detect_display_math_bool, + detect-family .bool_set:N = \l_@@_detect_family_bool, + detect-inline-family .choice:, + detect-inline-family .value_required:n = true, + detect-inline-family / + math .code:n = + { \tl_set:Nn \l_@@_detect_inline_family_tl { math } }, + detect-inline-family / + text .code:n = + { \tl_set:Nn \l_@@_detect_inline_family_tl { text } }, + detect-inline-weight .choice:, + detect-inline-weight .value_required:n = true, + detect-inline-weight / + math .code:n = + { \tl_set:Nn \l_@@_detect_inline_weight_tl { math } }, + detect-inline-weight / + text .code:n = + { \tl_set:Nn \l_@@_detect_inline_weight_tl { text } }, + detect-italic .bool_set:N = \l_@@_detect_shape_bool, + detect-mode .bool_set:N = \l_@@_detect_mode_bool, + detect-none .choice:, + detect-none .default:n = true, + detect-none / false .meta:n = + { + detect-family = true, + detect-mode = true, + detect-shape = true, + detect-weight = true + }, + detect-none / true .meta:n = + { + detect-family = false, + detect-mode = false, + detect-shape = false, + detect-weight = false + }, + detect-shape .bool_set:N = \l_@@_detect_shape_bool, + detect-weight .bool_set:N = \l_@@_detect_weight_bool +} +\keys_set:nn { siunitx } { + detect-inline-family = text , + detect-inline-weight = text , +} +% \end{macrocode} +%\end{macro} +% +%\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}{\@@_print_aux:} +% The main printing function does everything inside a group, as +% there are category code and definition changes to make. First, set +% the fonts. Then move on to printing mode, before moving to actual +% printing. +% \begin{macrocode} +\cs_new_protected:Npn \@@_print:nn #1#2 { + \group_begin: + \tl_set:Nn \l_@@_print_type_tl {#1} + \tl_set:Nn \l_@@_print_arg_tl {#2} + \@@_detect_font: + \bool_if:NF \l_@@_detect_mode_bool + { + \bool_if:cTF { l_@@_ #1 _math_mode_bool } + { \bool_set_true:N \l_@@_font_math_mode_bool } + { \bool_set_false:N \l_@@_font_math_mode_bool } + } + \@@_print_aux: + \group_end: +} +\cs_generate_variant:Nn \@@_print:nn { nV } +% \end{macrocode} +% The various font changes are set up, then the correct printing +% function is called. Everything is inside \cs{text} as this allows +% proper setting of the various mode settings. +% \begin{macrocode} +\cs_new_protected:Npn \@@_print_aux: + { + \text + { + \@@_ensure_ltr:n + { + \color@begingroup + \@@_print_color: + \@@_font_shape: + \@@_font_weight: + \use:c + { + @@_ \l_@@_print_type_tl _ + text \l_@@_font_family_tl : + } + \bool_if:NTF \l_@@_font_math_mode_bool + { \@@_print_math: } + { \@@_print_text: } + \color@endgroup + } + } + } +% \end{macrocode} +%\end{macro} +%\end{macro} +% +%\begin{macro}{ +% \@@_print_color: , +% \@@_textcolor:n +%} +% The colour system checks if \pkg{color} is loaded, and only does +% anything if it is. This will change when \LaTeX3 proper is available: +% there will be colour out of the box! +% \begin{macrocode} +\cs_new_protected:Npn \@@_print_color: { + \tl_if_empty:cF { l_@@_ \l_@@_print_type_tl _color_tl } + { + \color + { + \tl_use:c { l_@@_ \l_@@_print_type_tl _color_tl } + } + } +} +\AtBeginDocument { + \@ifpackageloaded { color } + { \cs_new_eq:NN \@@_textcolor:n \textcolor } + { + \cs_set_protected:Npn \@@_print_color: + { + \tl_if_empty:cF { l_@@_ \l_@@_print_type_tl _color_tl } + { + \cs_gset_eq:NN \@@_print_color: \scan_stop: + \msg_warning:nn { siunitx } { color-not-loaded } + } + } + \cs_new_protected:Npn \@@_textcolor:n #1 + { + \cs_gset_eq:NN \@@_textcolor:n \use_none:n + \msg_warning:nn { siunitx } { color-not-loaded } + } + } +} +% \end{macrocode} +%\end{macro} +% +% \begin{macro}{\@@_print_math:, \@@_print_text:} +% \begin{macro}{\@@_print_text_aux:} +% \begin{macro}{\@@_print_text_aux:NnN} +% Printing the text means replacing any awkward characters, which is +% dependent on the output mode. The rest of the package uses "_" and +% "^" to represent sub- and superscripts, respectively. In this way, +% mode decisions can be delayed as long as possible. The +% \pkg{underscore} package may make "_" active, or more likely +% it will be a superscript character. Both are tested for here. +% \begin{macrocode} +\cs_new_protected:Npn \@@_print_math: + { + \cs_set_eq:NN \PrintSubscript \sb + \cs_set_eq:NN \PrintSuperscript \sp + \ensuremath + { + \use:c + { + @@_ \l_@@_print_type_tl _ + math \l_@@_font_family_tl :n + } + { \l_@@_print_arg_tl } + } + } +\cs_new_protected:Npn \@@_print_text: + { + \tl_replace_all:Nnn \l_@@_print_arg_tl { - } + { \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 + \__siunitx_print_text_aux:NnN + _ { math_subscript } \@@_print_text_sub:n + _ { active } \@@_print_text_sub:n + ^ { math_superscript } \@@_print_text_super:n + ^ { active } \@@_print_text_super:n + \q_recursion_tail ? ? + \q_recursion_stop + \l_@@_print_arg_tl + } +\cs_new_protected:Npn \@@_print_text_aux: + { + \tl_replace_all:Nnn \l_@@_print_arg_tl { \pm } + { \ensuremath { \pm } } + } +\cs_new_protected:Npn \@@_print_text_aux:NnN #1#2#3 + { + \quark_if_recursion_tail_stop:N #1 + \tl_set_rescan:Nnn \l_@@_tmpa_tl + { \use:c { char_set_catcode_ #2 :N } #1 } + {#1} + \tl_replace_all:NVn \l_@@_print_arg_tl \l_@@_tmpa_tl {#3} + \_@@_print_text_aux:NnN + } +\AtBeginDocument + { + \@ifpackageloaded { textcomp } + { + \cs_set_protected:Npn \@@_print_text_aux: + { + \tl_replace_all:Nnn \l_@@_print_arg_tl { \pm } + { \textpm } + } + } + { } + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% +%\begin{macro}{ +% \@@_print_text_sub:n , +% \@@_print_text_super:n +%} +%\begin{macro}{\@@_print_text_sub_super:n} +% \begin{macro}{\@@_print_text_sub_peek:} +% \begin{macro}{\@@_peek_true:, \@@_peek_false:} +% The appropriate macros for sub- and superscript in text mode ensure +% the appearance is the same as math mode. The search and replace +% code for superscripts deals with the case where a literal number has +% been given with text mode printing. There is currently an issue with +% \pkg{expl3}'s \cs{peek_\ldots} functions, which means that the peek +% code is written out here in full. +% \begin{macrocode} +\cs_new_protected:Npn \@@_print_text_sub:n #1 + { + \cs_set:Npn \@@_print_text_sub_super:n ##1 + { + \ensuremath + { + \sb { \text {#1} } + \sp { \text {##1} } + } + } + \cs_set_protected:Npn \@@_peek_true: + { + \tex_afterassignment:D \@@_print_text_sub_super:n + \cs_set_eq:NN \@@_tmp:w + } + \cs_set_protected:Npn \@@_peek_false: + { \ensuremath { \sb { \text {#1} } } } + \peek_after:Nw \@@_print_text_sub_peek: + } +\cs_new_protected:Npn \@@_print_text_sub_peek: + { + \if_meaning:w \l_peek_token \@@_print_text_super:n + \exp_after:wN \@@_peek_true: + \else: + \exp_after:wN \@@_peek_false: + \fi: + } +\cs_new_protected:Npn \@@_peek_true: { } +\cs_new_protected:Npn \@@_peek_false: { } +\cs_new_protected:Npn \@@_print_text_sub_super:n { } +\cs_new_protected:Npn \@@_print_text_super:n #1 { + \tl_set:Nn \l_@@_tmpa_tl {#1} + \tl_replace_all:Nnn \l_@@_tmpa_tl { - } + { \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}{\@@_number_preprocess_product_aux:N} +% Rather than search through the entire argument, we use the +% delimited-argument trick. +% \begin{macrocode} +\cs_new_protected:Npn \@@_number_preprocess_product: { + \tl_map_function:NN \l_@@_input_product_tl + \@@_number_preprocess_product_aux:N +} +\cs_new_protected:Npn \@@_number_preprocess_product_aux:N #1 { + \tl_if_in:NnT \l_@@_number_arg_tl {#1} + { + \cs_set:Npn \@@_tmp:w ##1 #1 ##2 \q_stop + { + \tl_set:Nn \l_@@_number_arg_tl {##1} + \tl_set:Nn \l_@@_number_next_tl {##2} + \tl_set:Nn \l_@@_number_multi_tl { product } + } + \exp_after:wN \@@_tmp:w \l_@@_number_arg_tl \q_stop + \tl_if_empty:NT \l_@@_number_arg_tl + { \@@_error:n { starting-product-token } } + \tl_if_empty:NT \l_@@_number_next_tl + { \@@_error:n { ending-product-token } } + \tl_map_break: + } +} +% \end{macrocode} +%\end{macro} +%\end{macro} +% +%\begin{macro}{\@@_number_preprocess_quotient:} +%\begin{macro}{\@@_number_preprocess_quotient_aux:N} +% For the quotient, only one token can appear in each part. So there +% is an additional error check. +% \begin{macrocode} +\cs_new_protected:Npn \@@_number_preprocess_quotient: { + \tl_map_function:NN \l_@@_input_quotient_tl + \@@_number_preprocess_quotient_aux:N +} +\cs_new_protected:Npn \@@_number_preprocess_quotient_aux:N #1 { + \tl_if_in:NnT \l_@@_number_arg_tl {#1} + { + \cs_set:Npn \@@_tmp:w ##1 #1 ##2 \q_stop + { + \tl_set:Nn \l_@@_number_numerator_tl {##1} + \tl_set:Nn \l_@@_number_denominator_tl {##2} + \tl_set:Nn \l_@@_number_multi_tl { quotient } + } + \exp_after:wN \@@_tmp:w \l_@@_number_arg_tl \q_stop + \tl_if_empty:NT \l_@@_number_numerator_tl + { \@@_error:n { starting-quotient-token } } + \tl_if_empty:NT \l_@@_number_denominator_tl + { \@@_error:n { ending-quotient-token } } + \tl_if_in:NnT \l_@@_number_denominator_tl {#1} + { \@@_error:n { duplicate-quotient-token } } + \tl_map_break: + } +} +% \end{macrocode} +%\end{macro} +%\end{macro} +% +%\subsection{Parsing numbers} +% +% The parser is designed to be relativity fast, which means some code is +% more or less duplicated to gain more speed. It is also loaded so +% that simple numbers (such as \num{-1.23}) are parsed particularly +% quickly. For most documents, this gain more than offsets any slight +% losses with more complicated numbers. +% +%\begin{macro}{\c_@@_number_part_complex_tl} +% A couple of the comparisons needed for checking complex numbers +% are done using stored text. To make them a little quicker, a +% pre-stored version of the text is stored here. +% \begin{macrocode} +\tl_const:Nn \c_@@_number_part_complex_tl { complex } +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{ +% \l_@@_number_in_complex_bool , +% \l_@@_number_in_complex_root_bool , +% \l_@@_number_in_decimal_bool , +% \l_@@_number_in_exponent_bool , +% \l_@@_number_in_first_bool , +% \l_@@_number_in_sign_bool , +% \l_@@_number_in_uncert_bool , +% \l_@@_number_in_value_bool +%} +% \begin{macrocode} +\bool_new:N \l_@@_number_in_complex_bool +\bool_new:N \l_@@_number_in_complex_root_bool +\bool_new:N \l_@@_number_in_decimal_bool +\bool_new:N \l_@@_number_in_exponent_bool +\bool_new:N \l_@@_number_in_first_bool +\bool_new:N \l_@@_number_in_sign_bool +\bool_new:N \l_@@_number_in_uncert_bool +\bool_new:N \l_@@_number_in_value_bool +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\l_@@_number_in_prop} +% The parsed number is stored in a property list as its constituent +% parts. +% \begin{macrocode} +\prop_new:N \l_@@_number_in_prop +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\l_@@_number_parsed_tl} +% Each part of the number parsed has to be built up in a token list. +% \begin{macrocode} +\tl_new:N \l_@@_number_parsed_tl +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{ +% \l_@@_number_part_tl , +% \l_@@_number_part_decimal_tl , +% \l_@@_number_part_decimal_marker_tl , +% \l_@@_number_part_integer_tl , +% \l_@@_number_part_sign_tl , +% \l_@@_number_part_uncert_tl +%} +% The names of various parts of a number are set up as stored values. +% This lets some code be used for different parts of a number, while +% pre-storing everything brings a performance (and clarity) benefit. +% \begin{macrocode} +\tl_new:N \l_@@_number_part_tl +\tl_new:N \l_@@_number_part_decimal_tl +\tl_new:N \l_@@_number_part_decimal_marker_tl +\tl_new:N \l_@@_number_part_integer_tl +\tl_new:N \l_@@_number_part_sign_tl +\tl_new:N \l_@@_number_part_uncert_tl +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{ +% \l_@@_number_mantissa_length_int +% \l_@@_number_uncert_tl +% \l_@@_number_uncert_length_int +%} +% Conversion of uncertainty forms requires some storage, mainly for +% performance reasons. +% \begin{macrocode} +\int_new:N \l_@@_number_mantissa_length_int +\tl_new:N \l_@@_number_uncert_tl +\int_new:N \l_@@_number_uncert_length_int +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\l_@@_input_uncert_sign_tl} +% This one is stored by some low-level code, so is declared explicitly. +% \begin{macrocode} +\tl_new:N \l_@@_input_uncert_sign_tl +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{ +% \l_@@_input_uncert_close_tl , +% \l_@@_input_complex_tl , +% \l_@@_input_comparator_tl , +% \l_@@_input_decimal_tl , +% \l_@@_input_digit_tl , +% \l_@@_input_exponent_tl , +% \l_@@_input_ignore_tl , +% \l_@@_input_uncert_open_tl , +% \l_@@_input_protect_tl , +% \l_@@_input_sign_tl , +% \l_@@_input_symbol_tl , +% \l_@@_input_uncert_sign_tl +%} +% The various tokens to check against when parsing are all set up here. +% These are valid inside a single number: the pre-processor has already +% set up the appropriate things for products and quotients. +% \begin{macrocode} +\keys_define:nn { siunitx } { + input-close-uncertainty .tl_set:N = \l_@@_input_uncert_close_tl , + input-complex-roots .tl_set:N = \l_@@_input_complex_tl , + input-comparators .tl_set:N = \l_@@_input_comparator_tl , + input-decimal-markers .tl_set:N = \l_@@_input_decimal_tl , + input-digits .tl_set:N = \l_@@_input_digit_tl , + input-exponent-markers .tl_set:N = \l_@@_input_exponent_tl , + input-ignore .tl_set:N = \l_@@_input_ignore_tl , + input-open-uncertainty .tl_set:N = \l_@@_input_uncert_open_tl , + input-protect-tokens .tl_set:N = \l_@@_input_protect_tl , + input-signs .tl_set:N = \l_@@_input_sign_tl , + input-symbols .tl_set:N = \l_@@_input_symbol_tl , + input-uncertainty-signs .code:n = + { + \tl_set:Nn \l_@@_input_uncert_sign_tl {#1} + \tl_map_inline:nn {#1} + { + \tl_if_in:NnF \l_@@_input_sign_tl {##1} + { \tl_put_right:Nn \l_@@_input_sign_tl {##1} } + } + } , +} +\keys_set:nn { siunitx } { % ( + input-close-uncertainty = ), + input-complex-roots = ij, + input-comparators = {<=>\approx\ge\geq\gg\le\leq\ll\sim}, + input-decimal-markers = {.,}, + input-digits = 0123456789, + input-exponent-markers = dDeE, + input-open-uncertainty = (, % ) + input-protect-tokens = \approx\dots\ge\geq\gg\le\leq\ll\mp\pi\pm\sim, + input-signs = +-\mp\pm, + input-symbols = \dots\pi, + input-uncertainty-signs = \pm, +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{ +% \@@_number_in_parse:n , +% \@@_number_in_parse:V +%} +%\begin{macro}{\@@_number_in_parse_aux:n} +% The parsing routine starts by replacing any formatting in the input +% using \cs{tl_set_rescan:Nnx}. Next, there is a quick routine to +% ensure that all signs are single tokens. The main loop then takes +% place, which will parse the input into the property list and also +% set up the flags. There are then some checks and possible corrections. +% \begin{macrocode} +\cs_new_protected:Npn \@@_number_in_parse:n #1 { + \tl_if_empty:nF {#1} + { + \@@_number_in_init: + \cs_set_eq:NN \@@_number_in_parse_more:N + \@@_number_in_parse_mantissa_aux:N + \@@_number_in_parse_aux:n {#1} + } +} +\cs_generate_variant:Nn \@@_number_in_parse:n { V } +\group_begin: + \char_set_catcode_active:N \~ + \char_set_catcode_space:N \ % + \cs_new_protected:Npn \@@_number_in_parse_aux:n#1% + {% + \group_begin: + \@@_number_in_protect: + \cs_set_eq:NN\,\prg_do_nothing: + \cs_set_eq:NN~\prg_do_nothing: + \tl_set_rescan:Nnx\l_@@_number_arg_tl + {% + \char_set_catcode_ignore:N\ % + \char_set_catcode_other:N\,% + \char_set_catcode_other:N\.% + }% + {#1}% + \exp_args:NNNV\group_end: + \tl_set:Nn\l_@@_number_arg_tl\l_@@_number_arg_tl + \@@_number_in_sign_replace:N\l_@@_number_arg_tl + \@@_number_in_parse_relation:N\l_@@_number_arg_tl + \tl_map_function:NN\l_@@_number_arg_tl + \@@_number_in_parse_loop:N + \tl_if_empty:NF\l_@@_number_parsed_tl + {% + \bool_if:NTF\l_@@_number_in_uncert_bool + {\@@_error:nx{invalid-number}{#1}}% + {% + \prop_put:NVn \l_@@_number_in_prop + \l_@@_number_part_tl {true}% + \bool_if:NTF\l_@@_number_in_decimal_bool + {% + \prop_put:NVV\l_@@_number_in_prop + \l_@@_number_part_decimal_tl + \l_@@_number_parsed_tl + }% + {% + \prop_put:NVV\l_@@_number_in_prop + \l_@@_number_part_integer_tl + \l_@@_number_parsed_tl + }% + }% + }% + \@@_number_in_check:n {#1}% + } +\group_end: +% \end{macrocode} +%\end{macro} +%\end{macro} +% +%\begin{macro}{ +% \@@_number_in_init: , +% \@@_number_in_init_part:n +%} +% The set up code is divided into to parts. First, code only needed +% once to start the entire parser. Then a second group, which is +% carried out at the start of each part of a number, and so is called +% from a few places. +% \begin{macrocode} +\cs_new_protected:Npn \@@_number_in_init: { + \cs_set_eq:NN \@@_number_in_parse_loop:N + \@@_number_in_parse_mantissa:N + \cs_set_eq:NN \@@_number_in_check:n + \@@_number_in_check_short:n + \tl_clear:N \l_@@_number_parsed_tl + \prop_clear:N \l_@@_number_in_prop + \bool_set_false:N \l_@@_error_bool + \bool_set_false:N \l_@@_number_in_complex_bool + \bool_set_false:N \l_@@_number_in_complex_root_bool + \bool_set_false:N \l_@@_number_in_exponent_bool + \bool_set_false:N \l_@@_number_in_uncert_bool + \@@_number_in_init_part:n { mantissa } +} +\cs_new_protected:Npn \@@_number_in_init_part:n #1 { + \bool_set_false:N \l_@@_number_in_decimal_bool + \bool_set_true:N \l_@@_number_in_first_bool + \bool_set_false:N \l_@@_number_in_sign_bool + \bool_set_false:N \l_@@_number_in_value_bool + \tl_set:Nn \l_@@_number_part_tl {#1} + \tl_set:Nn \l_@@_number_part_decimal_tl { #1 -decimal } + \tl_set:Nn \l_@@_number_part_decimal_marker_tl + { #1 -decimal-marker } + \tl_set:Nn \l_@@_number_part_integer_tl { #1 -integer } + \tl_set:Nn \l_@@_number_part_sign_tl { #1 -sign } + \tl_set:Nn \l_@@_number_part_uncert_tl { #1 -uncertainty } +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\@@_number_in_protect:} +%\begin{macro}{\@@_number_in_protect_aux:N} +% Under some circumstances (for example when loading \pkg{breqn}) +% some tokens do not behave safely under \texttt{x} expansion (at the +% moment). To get round this, they are redefined here. +% \begin{macrocode} +\cs_new_protected:Npn \@@_number_in_protect: { + \tl_map_function:NN \l_@@_input_protect_tl + \@@_number_in_protect_aux:N +} +\cs_new_protected:Npn \@@_number_in_protect_aux:N #1 { + \cs_set_eq:NN #1 \scan_stop: +} +% \end{macrocode} +%\end{macro} +%\end{macro} +% +% \begin{macro}[int]{\@@_number_in_sign_replace:N} +% \begin{macro}{\@@_number_in_sign_replace_aux:N} +% \begin{macro}{\@@_number_in_sign_replace_aux:NnN} +% A short spin-out to keep the replacement of tokens clear. +% The case where |-| is active needs special treatment and +% needs to come first. +% \begin{macrocode} +\cs_new_protected:Npn \@@_number_in_sign_replace:N #1 + { + \@@_number_in_sign_replace_aux:N #1 + \@@_number_in_sign_replace_aux:NnN #1 + { -+ } \mp + { +- } \pm + { << } \ll + { <= } \le + { >> } \gg + { >= } \ge + { ?? } \q_recursion_tail + \q_recursion_stop + } +\group_begin: + \char_set_catcode_active:N - + \cs_new_protected:Npx \_@@_number_in_sign_replace_aux:N #1 + { \tl_replace_all:Nnn #1 { \exp_not:N - } { \token_to_str:N - } } +\group_end: +\cs_new_protected:Npn \@@_number_in_sign_replace_aux:NnN #1#2#3 + { + \quark_if_recursion_tail_stop:N #3 + \tl_replace_all:Nnn #1 {#2} {#3} + \@@_number_in_sign_replace_aux:NnN #1 + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% +%\begin{macro}{ +% \@@_number_in_parse_error:nn , +% \@@_number_in_parse_error:nV +%} +% There are lots of rather similar errors in the parser, all of which +% require a \cs{tl_map_break:}. To keep life simple, this is set up +% here. +% \begin{macrocode} +\cs_new_protected:Npn \@@_number_in_parse_error:nn #1#2 { + \@@_error:nx {#1} { \exp_not:n {#2} } + \tl_map_break: +} +\cs_generate_variant:Nn \@@_number_in_parse_error:nn { nV } +% \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}{\@@_number_in_parse_relation:w} +% The idea here is that a relation with be the very first token in the +% input, or it is not valid. So the test for a relation can be very +% simple and hopefully efficient. +% \begin{macrocode} +\cs_new_protected:Npn \@@_number_in_parse_relation:N #1 { + \exp_after:wN \@@_number_in_parse_relation:w #1 \q_stop #1 +} +\cs_new_protected:Npn \@@_number_in_parse_relation:w + #1#2 \q_stop #3 { + \tl_if_in:NnT \l_@@_input_comparator_tl {#1} + { + \prop_put:Nnn \l_@@_number_in_prop { comparator } {#1} + \tl_set:Nn #3 {#2} + } +} +% \end{macrocode} +%\end{macro} +%\end{macro} +% +%\begin{macro}{\@@_number_in_parse_restricted:N} +% When parsing numbers for the \cs{ang} function, no extended input +% is permitted at all. +% \begin{macrocode} +\cs_new_protected:Npn \@@_number_in_parse_restricted:N #1 { + \tl_if_in:NnTF \l_@@_input_exponent_tl {#1} + { + \@@_number_in_parse_error:nn + { restricted-number } {#1} + } + { + \tl_if_in:NnTF \l_@@_input_uncert_open_tl {#1} + { + \@@_number_in_parse_error:nV + { restricted-number } \l_@@_number_arg_tl + } + { + \tl_if_in:NnTF \l_@@_input_uncert_close_tl {#1} + { + \@@_number_in_parse_error:nV + { restricted-number } \l_@@_number_arg_tl + } + { + \tl_if_in:NnTF \l_@@_input_complex_tl {#1} + { + \@@_number_in_parse_error:nV + { restricted-number } \l_@@_number_arg_tl + } + { + \@@_number_in_parse_error:nn + { restricted-number } {#1} + } + } + } + } +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\@@_number_in_parse_complex:N} +% After a complex root when the root is \emph{after} the number, there +% are a very limited range of legitimate tokens. Thus most cases can be +% trapped with a modified parser. +% \begin{macrocode} +\cs_new_protected:Npn \@@_number_in_parse_complex:N #1 { + \tl_if_in:NnTF \l_@@_input_exponent_tl {#1} + { + \cs_set_eq:NN \@@_number_in_parse_loop:N + \@@_number_in_parse_mantissa:N + \@@_number_in_exponent:N #1 + } + { + \tl_if_in:NnF \l_@@_input_ignore_tl {#1} + { + \@@_number_in_parse_error:nV + { misplaced-complex-root-token } + \l_@@_number_arg_tl + } + } +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\@@_number_in_parse_exponent:N} +% When processing an exponent, the \enquote{extended} part of the +% number which is valid in a mantissa is no longer needed. So the +% auxiliary function is pointed to a series of errors instead. +% \begin{macrocode} +\cs_new_protected:Npn \@@_number_in_parse_exponent:N #1 { + \tl_if_in:NnTF \l_@@_input_exponent_tl {#1} + { + \@@_number_in_parse_error:nn + { duplicate-exponent-token } { \token_to_str:N #1 } + } + { + \tl_if_in:NnTF \l_@@_input_uncert_open_tl {#1} + { + \@@_number_in_parse_error:nV + { invalid-token-in-exponent } \l_@@_number_arg_tl + } + { + \tl_if_in:NnTF \l_@@_input_uncert_close_tl {#1} + { + \@@_number_in_parse_error:nV + { invalid-token-in-exponent } \l_@@_number_arg_tl + } + { + \tl_if_in:NnTF \l_@@_input_complex_tl {#1} + { + \@@_number_in_parse_error:nV + { invalid-token-in-exponent } + \l_@@_number_arg_tl + } + { + \@@_number_in_parse_error:nn + { invalid-token-in-number } {#1} + } + } + } + } +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\@@_number_in_parse_mantissa:N} +%\begin{macro}{\@@_number_in_parse_mantissa_aux:N} +% For the mantissa, most things are valid. The procedure is split +% into two parts, with the simple symbols handled here and the more +% complex ones in a second part(which needs to be varied). Essentially +% everything here is a comparison, done so that the code is a fast as +% possible. +% \begin{macrocode} +\cs_new_protected:Npn \@@_number_in_parse_mantissa:N #1 { + \tl_if_in:NnTF \l_@@_input_digit_tl {#1} + { \@@_number_in_digit:n {#1} } + { + \tl_if_in:NnTF \l_@@_input_decimal_tl {#1} + { \@@_number_in_decimal:N #1 } + { + \tl_if_in:NnTF \l_@@_input_sign_tl {#1} + { \@@_number_in_sign:N #1 } + { + \tl_if_in:NnTF \l_@@_input_symbol_tl {#1} + { + \prop_put:Nnn \l_@@_number_in_prop { symbolic } + { true } + \@@_number_in_digit:n {#1} + } + { + \tl_if_in:NnF \l_@@_input_ignore_tl {#1} + { \@@_number_in_parse_more:N #1 } + } + } + } + } +} +\cs_new_protected:Npn \@@_number_in_parse_mantissa_aux:N #1 { + \tl_if_in:NnTF \l_@@_input_exponent_tl {#1} + { \@@_number_in_exponent:N #1 } + { + \tl_if_in:NnTF \l_@@_input_uncert_open_tl {#1} + { \@@_number_in_uncert_open:N #1 } + { + \tl_if_in:NnTF \l_@@_input_uncert_close_tl {#1} + { + \@@_number_in_parse_error:nn + { misplaced-uncertainty-token } {#1} + } + { + \tl_if_in:NnTF \l_@@_input_complex_tl {#1} + { \@@_number_in_complex:N #1 } + { + \@@_number_in_parse_error:nn + { invalid-token-in-number } {#1} + } + } + } + } +} +% \end{macrocode} +%\end{macro} +%\end{macro} +% +%\begin{macro}{\@@_number_in_parse_uncert:N} +% Within uncertainties, the range of tokens is limited. An alternative +% parsing system can therefore be used. +% \begin{macrocode} +\cs_new_protected:Npn \@@_number_in_parse_uncert:N #1 { + \tl_if_in:NnTF \l_@@_input_digit_tl {#1} + { \@@_number_in_digit:n {#1} } + { + \tl_if_in:NnTF \l_@@_input_decimal_tl {#1} + { + \@@_number_in_parse_error:nV + { invalid-token-in-uncertainty } + \l_@@_number_arg_tl + } + { + \tl_if_in:NnTF \l_@@_input_sign_tl {#1} + { + \@@_number_in_parse_error:nV + { invalid-token-in-uncertainty } + \l_@@_number_arg_tl + } + { + \tl_if_in:NnTF \l_@@_input_symbol_tl {#1} + { + \prop_put:Nnn \l_@@_number_in_prop { symbolic } + { true } + \@@_number_in_digit:n {#1} + } + { + \tl_if_in:NnF \l_@@_input_ignore_tl {#1} + { + \tl_if_in:NnTF \l_@@_input_uncert_close_tl + {#1} + { \@@_number_in_uncert_close:N #1 } + { + \@@_number_in_parse_error:nV + { invalid-token-in-uncertainty } + \l_@@_number_arg_tl + } + } + } + } + } + } +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\@@_number_in_parse_uncert_after:N} +% After an uncertainty, there is once again a very limited range of +% tokens that can be present in a valid number. +% \begin{macrocode} +\cs_new_protected:Npn \@@_number_in_parse_uncert_after:N #1 { + \tl_if_in:NnTF \l_@@_input_exponent_tl {#1} + { + \cs_set_eq:NN \@@_number_in_parse_loop:N + \@@_number_in_parse_mantissa:N + \@@_number_in_exponent:N #1 + } + { + \tl_if_in:NnTF \l_@@_input_sign_tl {#1} + { + \cs_set_eq:NN \@@_number_in_parse_loop:N + \@@_number_in_parse_mantissa:N + \@@_number_in_sign:N #1 + } + { + \tl_if_in:NnF \l_@@_input_ignore_tl {#1} + { + \tl_if_in:NnTF \l_@@_input_complex_tl {#1} + { + \cs_set_eq:NN \@@_number_in_parse_loop:N + \@@_number_in_parse_mantissa:N + \@@_number_in_complex:N #1 + } + { + \@@_number_in_parse_error:nV { invalid-number } + \l_@@_number_arg_tl + } + } + } + } +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\@@_number_in_complex:N} +%\begin{macro}{\@@_number_in_complex_aux:nn} +% Only one complex root token can be give, hence the initial test. +% More tests are needed for complex numbers than other systems, so +% the additional ones are turned on, followed by some flag setting. +% The complex root is stored, then there is a check to see if the +% root is at the end of the number: if it is, prevent any more tokens +% being added. +% \begin{macrocode} +\cs_new_protected:Npn \@@_number_in_complex:N #1 { + \bool_set_false:N \l_@@_number_in_first_bool + \bool_if:NTF \l_@@_number_in_complex_root_bool + { + \@@_number_in_parse_error:nn + { duplicate-complex-root-token } { \token_to_str:N #1 } + } + { + \cs_set_eq:NN \@@_number_in_check:n + \@@_number_in_check_full:n + \bool_set_true:N \l_@@_number_in_complex_root_bool + \prop_put:Nnn \l_@@_number_in_prop { complex-root } {#1} + \tl_if_empty:NF \l_@@_number_parsed_tl + { + \cs_set_eq:NN \@@_number_in_parse_loop:N + \@@_number_in_parse_complex:N + } + \bool_if:NT \l_@@_number_in_decimal_bool + { + \bool_if:NF \l_@@_number_in_complex_bool + { + \prop_if_in:NnT \l_@@_number_in_prop + { mantissa-uncertainty } + { + \@@_number_in_complex_aux:nn + { mantissa-decimal } { complex-decimal } + \@@_number_in_complex_aux:nn + { mantissa-uncertainty } { complex-uncertainty } + } + \@@_number_in_complex_aux:nn { mantissa-integer } + { complex-integer } + \@@_number_in_complex_aux:nn + { mantissa-decimal-marker } { complex-decimal-marker } + \prop_remove:Nn \l_@@_number_in_prop { mantissa } + \prop_put:Nnn \l_@@_number_in_prop { complex } + { true } + } + } + \prop_if_in:NnF \l_@@_number_in_prop { mantissa } + { + \prop_if_in:NnT \l_@@_number_in_prop { mantissa-sign } + { + \@@_number_in_complex_aux:nn { mantissa-sign } + { complex-sign } + } + } + \bool_set_true:N \l_@@_number_in_complex_bool + \bool_set_false:N \l_@@_number_in_first_bool + \@@_number_in_init_part:n { complex } + \prop_if_in:NnT \l_@@_number_in_prop + { complex-decimal-marker } + { \bool_set_true:N \l_@@_number_in_decimal_bool } + \prop_if_in:NnTF \l_@@_number_in_prop + { complex-sign } + { \bool_set_true:N \l_@@_number_in_sign_bool } + { \prop_remove:Nn \l_@@_number_in_prop { mantissa } } + } +} +\cs_new_protected:Npn \@@_number_in_complex_aux:nn #1#2 { + \prop_get:NnNT \l_@@_number_in_prop {#1} \l_@@_tmpa_tl + { + \prop_remove:Nn \l_@@_number_in_prop {#1} + \prop_put:NnV \l_@@_number_in_prop {#2} \l_@@_tmpa_tl + } +} +% \end{macrocode} +%\end{macro} +%\end{macro} +% +%\begin{macro}{\@@_number_in_decimal:N} +% Only one decimal marker allowed, so a test for this. If an integer +% part has been found, it is saved. The flag for the number being +% found is not set unless there is an integer, to watch for the case +% of invalid numbers. +% \begin{macrocode} +\cs_new_protected:Npn \@@_number_in_decimal:N #1 { + \bool_set_false:N \l_@@_number_in_first_bool + \bool_if:NTF \l_@@_number_in_decimal_bool + { + \@@_number_in_parse_error:nn { duplicate-decimal-token } + {#1} + } + { + \bool_set_true:N \l_@@_number_in_decimal_bool + \tl_if_empty:NF \l_@@_number_parsed_tl + { + \prop_put:NVn \l_@@_number_in_prop + \l_@@_number_part_tl { true } + \prop_put:NVV \l_@@_number_in_prop + \l_@@_number_part_integer_tl + \l_@@_number_parsed_tl + \tl_clear:N \l_@@_number_parsed_tl + } + \prop_put:NVn \l_@@_number_in_prop + \l_@@_number_part_decimal_marker_tl {#1} + } +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\@@_number_in_digit:n} +% For digits, only in an uncertainty can the value be stored +% directly. Otherwise, there is a need to see if the value is non-zero. +% This is used to drop leading zeros and to validate any sign (as zero +% is unsigned). +% \begin{macrocode} +\cs_new_protected:Npn \@@_number_in_digit:n #1 { + \bool_set_false:N \l_@@_number_in_first_bool + \bool_if:NTF \l_@@_number_in_uncert_bool + { \tl_put_right:Nn \l_@@_number_parsed_tl {#1} } + { + \bool_if:NTF \l_@@_number_in_decimal_bool + { + \tl_put_right:Nn \l_@@_number_parsed_tl {#1} + \str_if_eq:nnF {#1} { 0 } + { \bool_set_true:N \l_@@_number_in_value_bool } + } + { + \str_if_eq:nnTF {#1} { 0 } + { + \prop_put:NVn \l_@@_number_in_prop + \l_@@_number_part_tl { true } + \prop_put:NVn \l_@@_number_in_prop + \l_@@_number_part_integer_tl { 0 } + } + { \bool_set_true:N \l_@@_number_in_value_bool } + \bool_if:NT \l_@@_number_in_value_bool + { \tl_put_right:Nn \l_@@_number_parsed_tl {#1} } + } + } +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\@@_number_in_exponent:N} +% A duplicate token test starts off the code, which if passed +% leads to some simple storage manipulation. As exponents are +% more simple than the mantissa, the extra processing is swapped for +% some that only raises errors. +% \begin{macrocode} +\cs_new_protected:Npn \@@_number_in_exponent:N #1 { + \bool_if:NTF \l_@@_number_in_exponent_bool + { + \@@_number_in_parse_error:nn { duplicate-exponent-token } + { \token_to_str:N #1 } + } + { + \cs_set_eq:NN \@@_number_in_parse_more:N + \@@_number_in_parse_exponent:N + \tl_if_empty:NF \l_@@_number_parsed_tl + { \@@_number_in_store: } + \bool_set_true:N \l_@@_number_in_exponent_bool + \@@_number_in_init_part:n { exponent } + } +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\@@_number_in_sign:N} +% The code for signs is complicated by complex numbers. A sign token +% must be the fist thing in a number, but after the real part of the +% mantissa a second sign token can appear to start a complex number. +% So most of the code here is to detect that case. +% \begin{macrocode} +\cs_new_protected:Npn \@@_number_in_sign:N #1 { + \bool_if:NTF \l_@@_number_in_first_bool + { + \bool_set_false:N \l_@@_number_in_first_bool + \bool_set_true:N \l_@@_number_in_sign_bool + \prop_put:NVn \l_@@_number_in_prop + \l_@@_number_part_sign_tl {#1} + } + { + \bool_if:NTF \l_@@_number_in_exponent_bool + { + \@@_number_in_parse_error:nn { misplaced-sign-token } + {#1} + } + { + \bool_if:NTF \l_@@_number_in_complex_bool + { + \@@_number_in_parse_error:nn + { misplaced-sign-token } {#1} + } + { + \tl_if_empty:NF \l_@@_number_parsed_tl + { \@@_number_in_store: } + \cs_set_eq:NN \@@_number_in_check:n + \@@_number_in_check_full:n + \@@_number_in_init_part:n { complex } + \prop_put:Nnn \l_@@_number_in_prop + { complex-sign } {#1} + \bool_set_true:N \l_@@_number_in_complex_bool + } + } + } +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{ +% \@@_number_in_uncert_open:N , +% \@@_number_in_uncert_close:N +%} +% Opening and closing uncertainty tokens are handled separately. For +% opening tokens, a check is made that there is something else to the +% number before collecting material up. For the closing token, the +% uncertainty must contain some numbers. A special loop function is then +% set up to prevent any additional digits after the closing token. +% \begin{macrocode} +\cs_new_protected:Npn \@@_number_in_uncert_open:N #1 { + \bool_set_false:N \l_@@_number_in_first_bool + \cs_set_eq:NN \@@_number_in_parse_loop:N + \@@_number_in_parse_uncert:N + \bool_set_true:N \l_@@_number_in_uncert_bool + \tl_if_empty:NTF \l_@@_number_parsed_tl + { + \prop_if_in:NVF \l_@@_number_in_prop + \l_@@_number_part_integer_tl + { + \@@_number_in_parse_error:nV { invalid-number } + \l_@@_number_arg_tl + } + } + { \@@_number_in_store: } +} +\cs_new_protected:Npn \@@_number_in_uncert_close:N #1 { + \bool_set_false:N \l_@@_number_in_uncert_bool + \tl_if_empty:NTF \l_@@_number_parsed_tl + { + \@@_number_in_parse_error:nV { empty-uncertainty } + \l_@@_number_arg_tl + } + { + \prop_put:NVV \l_@@_number_in_prop + \l_@@_number_part_uncert_tl \l_@@_number_parsed_tl + \prop_put:Nnn \l_@@_number_in_prop + { uncertainty } { true } + \tl_clear:N \l_@@_number_parsed_tl + \cs_set_eq:NN \@@_number_in_parse_loop:N + \@@_number_in_parse_uncert_after:N + } +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\@@_number_in_store:} +% A short auxiliary function needed in various places for storing +% either the integer or decimal part of a number, as appropriate. +% \begin{macrocode} +\cs_new_protected:Npn \@@_number_in_store: { + \prop_put:NVn \l_@@_number_in_prop \l_@@_number_part_tl + { true } + \bool_if:NTF \l_@@_number_in_decimal_bool + { + \prop_put:NVV \l_@@_number_in_prop + \l_@@_number_part_decimal_tl \l_@@_number_parsed_tl + } + { + \prop_put:NVV \l_@@_number_in_prop + \l_@@_number_part_integer_tl \l_@@_number_parsed_tl + } + \tl_clear:N \l_@@_number_parsed_tl +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{ +% \@@_number_in_check:n , +% \@@_number_in_check_short:n , +% \@@_number_in_check_full:n +%} +% The checks needed for a number depend on whether there is a complex +% part. In all cases, there must be some digits, as well as a sign or +% decimal marker. There is also a check for a zero-valued input, which +% has any sign deleted. For complex numbers, the check is needed in +% case there was no real part. +% \begin{macrocode} +\cs_new_protected:Npn \@@_number_in_check:n #1 { } +\cs_new_protected:Npn \@@_number_in_check_short:n #1 { + \prop_if_in:NVF \l_@@_number_in_prop + \l_@@_number_part_integer_tl + { + \prop_if_in:NVF \l_@@_number_in_prop + \l_@@_number_part_decimal_tl + { \@@_error:nx { invalid-number } {#1} } + } + \bool_if:NF \l_@@_number_in_value_bool + { + \tl_if_eq:NNF \l_@@_number_part_tl + \c_@@_number_part_complex_tl + { + \prop_get:NVNT \l_@@_number_in_prop + \l_@@_number_part_sign_tl \l_@@_tmpa_tl + { + \tl_set:Nx \l_@@_tmpb_tl + { \l_@@_number_part_sign_tl -deleted } + \prop_put:NVV \l_@@_number_in_prop + \l_@@_tmpb_tl \l_@@_tmpa_tl + } + \prop_remove:NV \l_@@_number_in_prop + \l_@@_number_part_sign_tl + } + } +} +\cs_new_protected:Npn \@@_number_in_check_full:n #1 { + \tl_if_eq:NNF \l_@@_number_part_tl + \c_@@_number_part_complex_tl + { \@@_number_in_check_short:n {#1} } + \bool_if:NF \l_@@_number_in_complex_root_bool + { + \prop_get:NnN \l_@@_number_in_prop { complex-sign } + \l_@@_tmpa_tl + \tl_if_in:NVTF \l_@@_input_uncert_sign_tl \l_@@_tmpa_tl + { + \prop_if_in:NnTF \l_@@_number_in_prop { uncertainty } + { + \@@_error:nx { misplaced-sign-token } + { \exp_not:n {#1} } + } + { \@@_number_in_complex_to_uncert:n {#1} } + } + { + \@@_error:nx { misplaced-sign-token } + { \exp_not:n {#1} } + } + } + \prop_get:NnNT \l_@@_number_in_prop { mantissa-sign } + \l_@@_tmpa_tl + { + \prop_if_in:NnF \l_@@_number_in_prop { mantissa } + { + \prop_remove:Nn \l_@@_number_in_prop { mantissa-sign } + \prop_put:NnV \l_@@_number_in_prop { complex-sign } + \l_@@_tmpa_tl + } + } +} +% \end{macrocode} +%\end{macro} +% +% +%\begin{macro}{\@@_number_in_complex_to_uncert:n} +%\begin{macro}{ +% \@@_number_in_complex_to_uncert_int: , +% \@@_number_in_complex_to_uncert_dec: +%} +% Internally, uncertainties are stored in \enquote{compact} form. +% The code here takes a putative complex part and converts it to +% a compact uncertainty, with checks for the cases where things look +% wrong. The method needed depends on whether there is an integer +% part. +% \begin{macrocode} +\cs_new_protected:Npn \@@_number_in_complex_to_uncert:n #1 { + \prop_remove:Nn \l_@@_number_in_prop { complex } + \prop_remove:Nn \l_@@_number_in_prop { complex-decimal-marker } + \prop_remove:Nn \l_@@_number_in_prop { complex-sign } + \prop_put:Nnn \l_@@_number_in_prop { uncertainty } { true } + \prop_get:NnNTF \l_@@_number_in_prop { complex-integer } + \l_@@_number_uncert_tl + { + \tl_if_single:NTF \l_@@_number_uncert_tl + { + \int_compare:nNnTF \l_@@_number_uncert_tl = 0 + { \@@_number_in_complex_to_uncert_dec:n {#1} } + { \@@_number_in_complex_to_uncert_int: } + } + { \@@_number_in_complex_to_uncert_int: } + } + { \@@_number_in_complex_to_uncert_dec:n {#1} } + \prop_remove:Nn \l_@@_number_in_prop { complex-integer } + \prop_remove:Nn \l_@@_number_in_prop { complex-decimal } +} +% \end{macrocode} +% When the input has an integer part to the uncertainty, the +% conversion is easy as all of the decimal part can be copied +% across. +% \begin{macrocode} +\cs_new_protected:Npn \@@_number_in_complex_to_uncert_int: { + \prop_get:NnNF \l_@@_number_in_prop { complex-decimal } + \l_@@_tmpa_tl + { \tl_clear:N \l_@@_tmpa_tl } + \prop_get:NnNF \l_@@_number_in_prop { mantissa-decimal } + \l_@@_tmpb_tl + { \tl_clear:N \l_@@_tmpb_tl } + \@@_number_in_complex_to_uncert_pad: +} +% \end{macrocode} +% For a number in which all of the uncertainty is in the decimal part, +% only the significant digits are needed. This means that a loop is +% needed to drop non-significant ones. +% \begin{macrocode} +\cs_new_protected:Npn \@@_number_in_complex_to_uncert_dec:n + #1 + { + \tl_clear:N \l_@@_number_uncert_tl + \prop_get:NnNTF \l_@@_number_in_prop { complex-decimal } + \l_@@_tmpa_tl + { + \prop_get:NnN \l_@@_number_in_prop { mantissa-decimal } + \l_@@_tmpb_tl + \quark_if_no_value:NT \l_@@_tmpb_tl + { \tl_clear:N \l_@@_tmpb_tl } + \tl_map_function:NN + \l_@@_tmpa_tl + \@@_number_in_complex_to_uncert_dec_loop:N + \@@_number_in_complex_to_uncert_pad: + } + { \@@_error:nx { misplaced-sign-token } { \exp_not:n {#1} } } + } +\cs_new_protected:Npn + \@@_number_in_complex_to_uncert_dec_loop:N #1 + { + \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_clear:N \l_@@_tmpb_tl } + \tl_set:Nx \l_@@_tmpb_tl + { + \exp_not:V \l_@@_tmpb_tl + \prg_replicate:nn + { + \l_@@_number_uncert_length_int + - \l_@@_number_mantissa_length_int + } + { 0 } + } + \tl_if_empty:NF \l_@@_tmpb_tl + { + \prop_put:NnV \l_@@_number_in_prop { mantissa-decimal } + \l_@@_tmpb_tl + \prop_if_in:NnF \l_@@_number_in_prop + { mantissa-decimal-marker } + { + \prop_put:Nnn \l_@@_number_in_prop + { mantissa-decimal-marker } { . } + } + } + } + \tl_put_right:NV \l_@@_number_uncert_tl \l_@@_tmpa_tl + \prop_put:NnV \l_@@_number_in_prop { mantissa-uncertainty } + \l_@@_number_uncert_tl + } +% \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}{\@@_number_process_exponent_aux:n} +% To check for a totally zero exponent, the possibility that one or more +% of the exponent storage areas is zero needs to be considered. +% \begin{macrocode} +\cs_new_protected:Npn \@@_number_process_exponent: { + \bool_if:NF \l_@@_process_zero_exponent_bool + { + \prop_if_in:NnT \l_@@_number_in_prop { exponent } + { + \bool_set_false:N \l_@@_tmp_bool + \@@_number_process_exponent_aux:n { integer } + \bool_if:NF \l_@@_tmp_bool + { \@@_number_process_exponent_aux:n { decimal } } + \bool_if:NF \l_@@_tmp_bool + { + \prop_remove:Nn \l_@@_number_in_prop { exponent } + \prop_remove:Nn \l_@@_number_in_prop + { exponent-integer } + \prop_remove:Nn \l_@@_number_in_prop + { exponent-decimal } + \prop_if_in:NnF \l_@@_number_in_prop { mantissa } + { + \prop_put:Nnn \l_@@_number_in_prop { mantissa } { true } + \prop_put:Nnn \l_@@_number_in_prop { mantissa-integer } { 1 } + } + } + } + } +} +\cs_new_protected:Npn \@@_number_process_exponent_aux:n #1 { + \prop_get:NnNT \l_@@_number_in_prop { exponent- #1 } + \l_@@_tmpa_tl + { + \int_compare:nNnF { \l_@@_tmpa_tl } = { 0 } + { \bool_set_true:N \l_@@_tmp_bool } + } +} +% \end{macrocode} +%\end{macro} +%\end{macro} +% +% \begin{macro}{\@@_number_process_figures:n} +% \begin{macro} +% { +% \@@_number_process_figures_aux:n , +% \@@_number_process_figures_init:n +% } +% The approach here is to find how many digits there are in each part +% of the number, working out which are significant. The next stage is +% reconstruction of the number. +% \begin{macrocode} +\cs_new_protected:Npn \@@_number_process_figures:n #1 + { + \int_compare:nNnTF \l_@@_process_precision_int > 0 + { + \prop_if_in:NnT \l_@@_number_in_prop {#1} + { \@@_number_process_figures_aux:n {#1} } + } + { + \prop_remove:Nn \l_@@_number_in_prop { #1 -sign } + \prop_put:Nnn \l_@@_number_in_prop { #1 -integer } { 0 } + \prop_remove:Nn \l_@@_number_in_prop { #1 -decimal } + \bool_if:NF \l_@@_process_int_to_dec_bool + { \prop_remove:Nn \l_@@_number_in_prop { #1 -decimal-marker } } + } + } +\cs_new_protected:Npn \@@_number_process_figures_aux:n #1 + { + \@@_number_process_figures_init:n {#1} + \@@_number_process_figures_count:n { integer } + \@@_number_process_figures_count:n { decimal } + \bool_if:NTF \l_@@_round_bool + { + \bool_set_false:N \l_@@_round_bool + \int_compare:nNnTF + \l_@@_round_int > \l_@@_process_precision_int + { + \@@_number_process_figures_round: + \@@_number_process_round_tidy:n {#1} + } + { \@@_number_process_figures_pad:n {#1} } + } + { + \prop_put:Nnn \l_@@_number_in_prop { #1 -integer } { 0 } + \prop_remove:Nn \l_@@_number_in_prop { #1 -decimal } + } + } +\cs_new_protected:Npn \@@_number_process_figures_init:n #1 + { + \int_zero:N \l_@@_round_int + \bool_set_false:N \l_@@_round_bool + \bool_set_false:N \l_@@_round_even_bool + \prop_get:NnNF \l_@@_number_in_prop { #1 -decimal } + \l_@@_round_decimal_in_tl + { \tl_clear:N \l_@@_round_decimal_in_tl } + \prop_get:NnNF \l_@@_number_in_prop { #1 -integer } + \l_@@_round_integer_in_tl + { \tl_clear:N \l_@@_round_integer_in_tl } + \tl_clear:N \l_@@_round_decimal_out_tl + \tl_clear:N \l_@@_round_integer_out_tl + \tl_clear:N \l_@@_round_discard_tl + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \begin{macro}{\@@_number_process_figures_count:n} +% \begin{macro}{\@@_number_process_figures_count_aux:n} +% The counting code has to check that characters are actually +% significant. +% \begin{macrocode} +\cs_new_protected:Npn \@@_number_process_figures_count:n #1 + { + \tl_if_empty:cF { l_@@_round_ #1 _in_tl } + { + \prop_if_in:NnF \l_@@_number_in_prop { #1 -uncertainty } + { \@@_number_process_figures_count_aux:n {#1} } + } + } +\cs_new_protected:Npn \@@_number_process_figures_count_aux:n #1 + { + \int_set:Nn \l_@@_tmp_int + { \tl_head:v { l_@@_round_ #1 _in_tl } } + \tl_set:cx { l_@@_round_ #1 _in_tl } + { \tl_tail:v { l_@@_round_ #1 _in_tl } } + \tl_put_left:cV { l_@@_round_ #1 _out_tl } \l_@@_tmp_int + \bool_if:NF \l_@@_round_bool + { + \int_compare:nNnF \l_@@_tmp_int = 0 + { \bool_set_true:N \l_@@_round_bool } + } + \bool_if:NT \l_@@_round_bool + { \int_incr:N \l_@@_round_int } + \tl_if_empty:cTF { l_@@_round_ #1 _in_tl } + { + \tl_set_eq:cc { l_@@_round_ #1 _in_tl } + { l_@@_round_ #1 _out_tl } + \tl_clear:c { l_@@_round_ #1 _out_tl } + } + { \@@_number_process_figures_count_aux:n {#1} } + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \begin{macro}{\@@_number_process_figures_round:} +% \begin{macro}{\@@_number_process_figures_round_loop:} +% The control macro for rounding to figures does the decimal part +% then the integer part as loops. There is then some tidying up if a +% digit is carried at the end. +% \begin{macrocode} +\cs_new_protected:Npn \@@_number_process_figures_round: + { + \int_set:Nn \l_@@_round_int + { \l_@@_round_int - \l_@@_process_precision_int } + \tl_if_empty:NF \l_@@_round_decimal_in_tl + { \@@_number_process_figures_round_loop: } + \tl_if_empty:NF \l_@@_round_integer_in_tl + { \@@_number_process_figures_integer: } + \bool_if:NT \l_@@_round_bool + { \tl_put_left:Nn \l_@@_round_integer_out_tl { 1 } } + } +\cs_new_protected:Npn \@@_number_process_figures_round_loop: + { + \@@_number_process_round_decimal: + \tl_if_empty:NF \l_@@_round_decimal_in_tl + { \@@_number_process_figures_round_loop: } + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \begin{macro}{\@@_number_process_figures_integer:} +% For figures, the integer part is a little complicated as zeros need +% to be included. +% \begin{macrocode} +\cs_new_protected:Npn \@@_number_process_figures_integer: + { + \int_compare:nNnT \l_@@_round_int > 0 + { \tl_put_left:Nn \l_@@_round_integer_out_tl { 0 } } + \int_compare:nNnF \l_@@_round_int > 1 + { + \int_set:Nn \l_@@_tmp_int + { \tl_head:N \l_@@_round_integer_in_tl } + \@@_number_process_round_up: + \int_compare:nNnTF \l_@@_round_int = 1 + { + \int_compare:nNnT \l_@@_tmp_int > 4 + { \bool_set_true:N \l_@@_round_bool } + } + { + \int_compare:nNnT \l_@@_tmp_int = { 10 } + { + \bool_set_true:N \l_@@_round_bool + \int_zero:N \l_@@_tmp_int + } + \tl_put_left:NV \l_@@_round_integer_out_tl + \l_@@_tmp_int + } + } + \int_decr:N \l_@@_round_int + \tl_set:Nx \l_@@_round_integer_in_tl + { \tl_tail:N \l_@@_round_integer_in_tl } + \tl_if_empty:NF \l_@@_round_integer_in_tl + { \@@_number_process_figures_integer: } + } +% \end{macrocode} +%\end{macro} +%\begin{macro}{\@@_number_process_figures_pad:n} +% If the number is too short, then the reversal is undone and the +% padding routine is called. +% \begin{macrocode} +\cs_new_protected:Npn \@@_number_process_figures_pad:n #1 { + \prop_get:NnN \l_@@_number_in_prop { #1 -integer } + \l_@@_round_integer_in_tl + \prop_get:NnN \l_@@_number_in_prop { #1 -decimal } + \l_@@_round_decimal_in_tl + \int_set:Nn \l_@@_round_int + { \l_@@_process_precision_int - \l_@@_round_int } + \@@_number_process_pad:n {#1} +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\@@_number_process_fixed:} +%\begin{macro}{ +% \@@_number_process_fixed_aux_i:nnn , +% \@@_number_process_fixed_aux_ii:nnn , +% \@@_number_process_fixed_aux_iii:nnn , +% \@@_number_process_fixed_large:nnn , +% \@@_number_process_fixed_large_aux:w , +% \@@_number_process_fixed_small:nnn , +% \@@_number_process_fixed_small_aux:w +%} +% When working to a fixed exponent value, the idea is to use the stack +% to do the work. First, there is some set up to do. +% \begin{macrocode} +\cs_new_protected:Npn \@@_number_process_fixed: { + \prop_if_in:NnF \l_@@_number_in_prop { complex } + { + \prop_get:NnNF \l_@@_number_in_prop { mantissa-integer } + \l_@@_tmpa_tl + { \tl_set:Nn \l_@@_tmpa_tl { 0 } } + \prop_get:NnNF \l_@@_number_in_prop { mantissa-decimal } + \l_@@_tmpb_tl + { \tl_clear:N \l_@@_tmpb_tl } + \tl_set:Nx \l_@@_tmpa_tl + { { \l_@@_tmpa_tl } { \l_@@_tmpb_tl } } + \prop_get:NnNF \l_@@_number_in_prop { exponent-integer } + \l_@@_tmpb_tl + { \tl_set:Nn \l_@@_tmpb_tl { 0 } } + \group_begin: + \prop_get:NnNT \l_@@_number_in_prop { exponent-sign } + \l_@@_tmpa_tl + { + \tl_put_left:NV \l_@@_tmpb_tl \l_@@_tmpa_tl + } + \exp_args:NNNV \group_end: + \tl_set:Nn \l_@@_tmpb_tl \l_@@_tmpb_tl + \tl_set:Nx \l_@@_tmpa_tl + { \l_@@_tmpa_tl { \l_@@_tmpb_tl } } + \exp_after:wN \@@_number_process_fixed_aux_i:nnn + \l_@@_tmpa_tl + } +} +% \end{macrocode} +% The main loop checks to see which way to adjust the exponent then +% does the work. +% \begin{macrocode} +\cs_new_protected:Npn \@@_number_process_fixed_aux_i:nnn #1#2#3 + { + \prop_put:Nnn \l_@@_number_in_prop { exponent } { true } + \int_compare:nNnTF \l_@@_process_fixed_int > 0 + { + \prop_put:NnV \l_@@_number_in_prop { exponent-integer } + \l_@@_process_fixed_int + \prop_remove:Nn \l_@@_number_in_prop { exponent-sign } + } + { + \prop_put:Nnx \l_@@_number_in_prop { exponent-integer } + { \int_eval:n { - \l_@@_process_fixed_int } } + \prop_put:Nnn \l_@@_number_in_prop { exponent-sign } { - } + } + \@@_number_process_fixed_aux_ii:nnn {#1} {#2} {#3} + } +\cs_new_protected:Npn \@@_number_process_fixed_aux_ii:nnn #1#2#3 + { + \bool_set_true:N \l_@@_tmp_bool + \tl_map_inline:nn {#1#2} + { + \str_if_eq:nnF {##1} { 0 } + { + \bool_set_false:N \l_@@_tmp_bool + \tl_map_break: + } + } + \bool_if:NF \l_@@_tmp_bool + { \@@_number_process_fixed_aux_iii:nnn {#1} {#2} {#3} } + } +\cs_new_protected:Npn + \@@_number_process_fixed_aux_iii:nnn #1#2#3 { + \int_compare:nNnTF {#3} > { \l_@@_process_fixed_int } + { \@@_number_process_fixed_large:nnn {#1} {#2} {#3} } + { + \int_compare:nNnTF {#3} < { \l_@@_process_fixed_int } + { \@@_number_process_fixed_small:nnn {#1} {#2} {#3} } + { + \prop_put:Nnn \l_@@_number_in_prop + { mantissa-integer } {#1} + \tl_if_empty:nTF {#2} + { + \prop_remove:Nn \l_@@_number_in_prop + { mantissa-decimal } + \prop_remove:Nn \l_@@_number_in_prop + { mantissa-decimal-marker } + } + { + \prop_put:Nnn \l_@@_number_in_prop + { mantissa-decimal } {#2} + \prop_if_in:NnF \l_@@_number_in_prop + { mantissa-decimal-marker } + { + \prop_put:Nnn \l_@@_number_in_prop + { mantissa-decimal-marker } { . } + } + } + } + } +} +% \end{macrocode} +% Simple stack-based manipulation of the input for number which are +% either too big or too small. There are a couple of checks needed to +% deal with cases where there is no decimal part and where there are +% leading zeros to dispose of. There is also a check to avoid adding +% an additional zero to the decimal part of the number. +% \begin{macrocode} +\cs_new_protected:Npn \@@_number_process_fixed_large:nnn #1 + { + \@@_number_if_zero:nTF {#1} + { \@@_number_process_fixed_large_aux:nnn { } } + { \@@_number_process_fixed_large_aux:nnn {#1} } + } +\cs_new_protected:Npn \@@_number_process_fixed_large_aux:nnn #1#2#3 + { + \cs_set_protected:Npn + \@@_number_process_fixed_large_aux:w ##1##2 \q_stop + { + \tl_if_empty:nTF {##2} + { + \int_compare:nNnTF + { #3 - 1 } = { \l_@@_process_fixed_int } + { + \@@_number_process_fixed_aux_ii:nnn { #1 ##1 } + { } { #3 - 1 } + } + { + \@@_number_process_fixed_aux_ii:nnn { #1 ##1 } + { 0 } { #3 - 1 } + } + } + { + \@@_number_if_zero:nTF {#1} + { + \@@_number_process_fixed_aux_ii:nnn {##1} {##2} + { #3 - 1 } + } + { + \@@_number_process_fixed_aux_ii:nnn { #1 ##1 } + {##2} { #3 - 1 } + } + } + } + \tl_if_empty:nTF {#2} + { \@@_number_process_fixed_aux_ii:nnn { #1 0 } { } { #3 - 1 } } + { \@@_number_process_fixed_large_aux:w #2 \q_stop } +} +\cs_new_protected:Npn \@@_number_process_fixed_large_aux:w + { } +\cs_new_protected:Npn + \@@_number_process_fixed_small:nnn #1#2#3 { + \cs_set_protected:Npn + \@@_number_process_fixed_small_aux:w ##1##2 \q_stop ##3 + { + \tl_if_empty:nTF {##2} + { + \tl_if_empty:nTF {##3} + { + \@@_number_process_fixed_aux_ii:nnn { 0 } + { ##1 #2 } { #3 + 1 } + } + { + \@@_number_process_fixed_aux_ii:nnn {##3} + { ##1 #2 } { #3 + 1 } + } + } + { + \@@_number_process_fixed_small_aux:w ##2 \q_stop + { ##3 ##1 } + } + } + \@@_number_process_fixed_small_aux:w #1 \q_stop { } +} +\cs_new_protected:Npn \@@_number_process_fixed_small_aux:w + { } +% \end{macrocode} +%\end{macro} +%\end{macro} +% +%\begin{macro}{\@@_number_process_integer_digits:} +% Producing extra digits for the integer part is a simple process +% once the target is known. +% \begin{macrocode} +\cs_new_protected:Npn \@@_number_process_integer_digits: { + \int_compare:nNnT \l_@@_process_integer_min_int > 0 + { + \prop_get:NnNT \l_@@_number_in_prop { mantissa-integer } + \l_@@_tmpa_tl + { + \int_set:Nn \l_@@_tmp_int + { + \l_@@_process_integer_min_int + - \tl_count:N \l_@@_tmpa_tl + } + \int_compare:nNnT \l_@@_tmp_int > 0 + { + \tl_set:Nx \l_@@_tmpa_tl + { + \prg_replicate:nn { \l_@@_tmp_int } { 0 } + \exp_not:V \l_@@_tmpa_tl + } + \prop_put:NnV \l_@@_number_in_prop + { mantissa-integer } \l_@@_tmpa_tl + } + } + } +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\@@_number_process_mantissa:} +%\begin{macro}{\c_@@_unity_tl} +% A check for the mantissa consisting only of the token \texttt{1}, when +% an exponent is also available. +% \begin{macrocode} +\cs_new_protected:Npn \@@_number_process_mantissa: { + \bool_if:NF \l_@@_process_unity_mantissa_bool + { + \prop_if_in:NnT \l_@@_number_in_prop { exponent } + { + \prop_get:NnNT \l_@@_number_in_prop { mantissa-integer } + \l_@@_tmpa_tl + { + \tl_if_eq:NNT \c_@@_unity_tl \l_@@_tmpa_tl + { + \prop_if_in:NnF \l_@@_number_in_prop + { mantissa-decimal-marker } + { + \prop_remove:Nn \l_@@_number_in_prop + { mantissa } + \prop_remove:Nn \l_@@_number_in_prop + { mantissa-integer } + } + } + } + } + } +} +\tl_const:Nn \c_@@_unity_tl { 1 } +% \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} +% { +% \@@_number_process_places_init:n , +% \@@_number_process_places_aux_i:n , +% \@@_number_process_places_aux_i:TF , +% \@@_number_process_places_none: , +% \@@_number_process_places_aux_ii:n , +% \@@_number_process_places_loop:n , +% \@@_number_process_places_integer:n +% } +% For rounding to a fixed number of places, a check is made to see if +% the decimal part is exactly zero. If it is, just create the +% appropriate number of zeros in the padding routine. Otherwise, do the +% real work. +% \begin{macrocode} +\cs_new_protected:Npn \@@_number_process_places:n #1 + { + \prop_if_in:NnT \l_@@_number_in_prop {#1} + { + \prop_if_in:NnF \l_@@_number_in_prop { #1 -uncertainty } + { \@@_number_process_places_aux_i:n {#1} } + } + } +\cs_new_protected:Npn \@@_number_process_places_aux_i:n #1 + { + \int_compare:nNnTF \l_@@_process_precision_int = 0 + { \@@_number_process_places_none:n {#1} } + { + \prop_get:NnNT \l_@@_number_in_prop { #1 -decimal } + \l_@@_tmpa_tl + { + \tl_if_empty:NT \l_@@_tmpa_tl + { \tl_set:Nn \l_@@_tmpa_tl { 0 } } + \@@_number_process_places_aux_i:TF + { + \prop_put:Nnn \l_@@_number_in_prop { #1 -decimal } { } + \int_set:Nn \l_@@_round_int + { \l_@@_process_precision_int } + \@@_number_process_pad:n {#1} + } + { + \int_set:Nn \l_@@_round_int + { \tl_count:N \l_@@_tmpa_tl } + \@@_number_process_places_aux_ii:n {#1} + } + } + } + } +% \end{macrocode} +% The number of digits in the decimal part could be more that \TeX{} can +% handle, so a slow loop is used to see if we need to round. +% \begin{macrocode} +\cs_new_protected:Npn \@@_number_process_places_aux_i:TF + { + \bool_set_true:N \l_@@_tmp_bool + \tl_map_inline:Nn \l_@@_tmpa_tl + { + \int_compare:nNnF {##1} = 0 + { + \bool_set_false:N \l_@@_tmp_bool + \tl_map_break: + } + } + \bool_if:NTF \l_@@_tmp_bool + } +% \end{macrocode} +% Rounding to no places at all requires a few checks to see if there is any +% work to do. That includes a check for rounding half to even, where if +% the decimal part is exactly half then special action is required. +% \begin{macrocode} +\cs_new_protected:Npn \@@_number_process_places_none:n #1 + { + \prop_get:NnNT \l_@@_number_in_prop { #1 -decimal } \l_@@_tmpa_tl + { + \int_compare:nNnTF { \tl_head:N \l_@@_tmpa_tl } > 4 + { + \prop_get:NnNTF \l_@@_number_in_prop { #1 -integer } + \l_@@_tmpb_tl + { + \tl_set:Nx \l_@@_tmpb_tl + { \int_eval:n { \l_@@_tmpb_tl + 1 } } + \bool_if:NF \l_@@_round_half_up_bool + { + \int_compare:nNnT + { 0 \tl_tail:N \l_@@_tmpa_tl } = 0 + { + \int_if_odd:nT \l_@@_tmpb_tl + { + \tl_set:Nx \l_@@_tmpb_tl + { \int_eval:n { \l_@@_tmpb_tl - 1 } } + } + } + } + } + { \tl_set:Nn \l_@@_tmpb_tl { 1 } } + \prop_put:NnV \l_@@_number_in_prop + { #1 -integer } \l_@@_tmpb_tl + } + { + \prop_if_in:NnF \l_@@_number_in_prop { #1 -integer } + { + \prop_put:Nnn \l_@@_number_in_prop + { #1 -integer } { 0 } + } + } + } + \prop_remove:Nn \l_@@_number_in_prop { #1 -decimal } + \bool_if:NF \l_@@_process_int_to_dec_bool + { \prop_remove:Nn \l_@@_number_in_prop { #1 -decimal-marker } } + } +% \end{macrocode} +% For rounding to a fixed number of places, the package finds the +% difference in length between what is present and what is required. +% If the number is too short, there is some simple padding to do. +% \begin{macrocode} +\cs_new_protected:Npn \@@_number_process_places_aux_ii:n #1 + { + \int_sub:Nn \l_@@_round_int + { \l_@@_process_precision_int } + \int_compare:nNnTF \l_@@_round_int < 0 + { + \int_set:Nn \l_@@_round_int { - \l_@@_round_int } + \@@_number_process_pad:n {#1} + } + { + \@@_number_process_places_init:n {#1} + \@@_number_process_places_loop:n {#1} + \@@_number_process_round_tidy:n {#1} + } + } +% \end{macrocode} +% To keep the code a little clearer. +% \begin{macrocode} +\cs_new_protected:Npn \@@_number_process_places_init:n #1 + { + \prop_get:NnNF \l_@@_number_in_prop { #1 -integer } + \l_@@_round_integer_in_tl + { \tl_clear:N \l_@@_round_integer_in_tl } + \prop_get:NnN \l_@@_number_in_prop { #1 -decimal } + \l_@@_round_decimal_in_tl + \tl_reverse:N \l_@@_round_integer_in_tl + \tl_reverse:N \l_@@_round_decimal_in_tl + \tl_clear:N \l_@@_round_integer_out_tl + \tl_clear:N \l_@@_round_decimal_out_tl + \tl_clear:N \l_@@_round_discard_tl + \bool_set_false:N \l_@@_round_bool + \bool_set_false:N \l_@@_round_even_bool + } +% \end{macrocode} +% If there is a decimal, do the decimal processing then come back here. +% If there is an integer, do the same. Only if both are empty does the +% loop stop. +% \begin{macrocode} +\cs_new_protected:Npn \@@_number_process_places_loop:n #1 + { + \tl_if_empty:NTF \l_@@_round_decimal_in_tl + { + \tl_if_empty:NF \l_@@_round_integer_in_tl + { + \@@_number_process_places_integer:n {#1} + \@@_number_process_places_loop:n {#1} + } + \bool_if:NT \l_@@_round_bool + { + \tl_put_left:Nn \l_@@_round_integer_out_tl { 1 } + \bool_set_false:N \l_@@_round_bool + } + } + { + \@@_number_process_round_decimal: + \@@_number_process_places_loop:n {#1} + } + } +% \end{macrocode} +% Rounding for integers is just a case of carrying digits. +% \begin{macrocode} +\cs_new_protected:Npn \@@_number_process_places_integer:n #1 + { + \int_set:Nn \l_@@_tmp_int + { \tl_head:N \l_@@_round_integer_in_tl } + \tl_set:Nx \l_@@_round_integer_in_tl + { \tl_tail:N \l_@@_round_integer_in_tl } + \@@_number_process_round_up: + \bool_set_false:N \l_@@_round_bool + \int_compare:nNnT \l_@@_tmp_int = { 10 } + { + \int_zero:N \l_@@_tmp_int + \bool_set_true:N \l_@@_round_bool + } + \tl_put_left:NV \l_@@_round_integer_out_tl \l_@@_tmp_int + } +% \end{macrocode} +%\end{macro} +%\end{macro} +% +% \begin{macro}{\@@_number_process_round:} +% The lead-off for rounding is the same for decimal places and +% significant figures. +% \begin{macrocode} +\cs_new_protected:Npn \@@_number_process_round: + { + \tl_if_empty:NF \l_@@_round_tl + { + \bool_if:NT \l_@@_process_int_to_dec_bool + { + \prop_if_in:NnF \l_@@_number_in_prop { mantissa-decimal } + { + \prop_put:Nnn \l_@@_number_in_prop { mantissa-decimal } + { 0 } + } + \prop_if_in:NnF \l_@@_number_in_prop + { mantissa-decimal-marker } + { + \prop_put:Nnn \l_@@_number_in_prop + { mantissa-decimal-marker } { . } + } + } + \clist_map_function:nc { mantissa , complex } + { @@_number_process_ \l_@@_round_tl :n } + } + } +% \end{macrocode} +% \end{macro} +% \begin{macro}{\@@_number_process_round_decimal:} +% \begin{macro}{\@@_number_process_round_decimal_aux:} +% The rounding routine for decimals is the same for figures and places, +% so there is a generalised function here. Unfortunately, it is also +% complicated! +% \begin{macrocode} +\cs_new_protected:Npn \@@_number_process_round_decimal: + { + \int_compare:nNnF \l_@@_round_int > 1 + { \@@_number_process_round_decimal_aux: } + \tl_put_right:Nx \l_@@_round_discard_tl + { \tl_head:N \l_@@_round_decimal_in_tl } + \tl_set:Nx \l_@@_round_decimal_in_tl + { \tl_tail:N \l_@@_round_decimal_in_tl } + \int_decr:N \l_@@_round_int + } +% \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 = 1 + { + \int_compare:nNnT \l_@@_tmp_int > 4 + { + \bool_set_true:N \l_@@_round_bool + \bool_if:NF \l_@@_round_half_up_bool + { + \int_compare:nNnT + { \l_@@_round_discard_tl \int_use:N \l_@@_tmp_int } = 5 + { \bool_set_true:N \l_@@_round_even_bool } + } + } + } + { + \int_compare:nNnT \l_@@_tmp_int = { 10 } + { + \bool_set_true:N \l_@@_round_bool + \int_zero:N \l_@@_tmp_int + } + \tl_put_left:NV \l_@@_round_decimal_out_tl + \l_@@_tmp_int + } + } +% \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}{\@@_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 + { + \bool_lazy_and:nnTF + { \@@_number_if_zero_p:V \l_@@_round_integer_out_tl } + { \@@_number_if_zero_p:V \l_@@_round_decimal_out_tl } + { + \str_if_eq:VnTF \l_@@_process_round_min_tl { 0 } + { + \prop_put:Nnn \l_@@_number_in_prop { #1 -integer } { 0 } + \prop_put:NnV \l_@@_number_in_prop { #1 -decimal } + \l_@@_round_decimal_out_tl + } + { + \exp_after:wN \@@_number_process_round_tidy_aux:w + \l_@@_process_round_min_tl . . \q_stop {#1} + } + } + { + \prop_put:NnV \l_@@_number_in_prop { #1 -integer } + \l_@@_round_integer_out_tl + \tl_if_empty:NTF \l_@@_round_decimal_out_tl + { + \prop_remove:Nn \l_@@_number_in_prop { #1 -decimal } + \prop_remove:Nn \l_@@_number_in_prop { #1 -decimal-marker } + } + { + \prop_put:NnV \l_@@_number_in_prop { #1 -decimal } + \l_@@_round_decimal_out_tl + } + } + } +\cs_new_protected:Npn \@@_number_process_round_tidy_aux:w + #1 . #2 . #3 \q_stop #4 + { + \prop_put:Nnn \l_@@_number_in_prop { comparator } { < } + \prop_put:Nnn \l_@@_number_in_prop { #4 -integer } {#1} + \tl_if_empty:nTF {#2} + { \prop_remove:Nn \l_@@_number_in_prop { #4 -decimal } } + { \prop_put:Nnn \l_@@_number_in_prop { #4 -decimal } {#2} } + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +%\begin{macro}{\@@_number_process_scientific:} +%\begin{macro}{ +% \@@_number_process_scientific_aux_i:nnn , +% \@@_number_process_scientific_aux_ii:nnn , +% \@@_number_process_scientific_large:nnn , +% \@@_number_process_scientific_large_loop:nNN , +% \@@_number_process_scientific_small:wn , +% \@@_number_process_scientific_store:nnn , +% \@@_number_process_scientific_engineering:nnn , +% \@@_number_process_scientific_engineering_0:nnn , +% \@@_number_process_scientific_engineering_1:nnn , +% \@@_number_process_scientific_engineering_1:nw , +% \@@_number_process_scientific_engineering_2:nnn , +% \@@_number_process_scientific_engineering_2_i:nw , +% \@@_number_process_scientific_engineering_2_ii:nw +%} +% Converting a number to scientific form is done such that the number +% of places involved is unchanged. The first step is to skip any +% complex-number containing input and to recover the stored data. +% \begin{macrocode} +\cs_new_protected:Npn \@@_number_process_scientific: { + \prop_if_in:NnF \l_@@_number_in_prop { complex } + { + \prop_get:NnNF \l_@@_number_in_prop { mantissa-integer } + \l_@@_tmpa_tl + { \tl_set:Nn \l_@@_tmpa_tl { 0 } } + \prop_get:NnNF \l_@@_number_in_prop { mantissa-decimal } + \l_@@_tmpb_tl + { \tl_clear:N \l_@@_tmpb_tl } + \tl_set:Nx \l_@@_tmpa_tl + { { \l_@@_tmpa_tl } { \l_@@_tmpb_tl } } + \prop_get:NnNF \l_@@_number_in_prop { exponent-integer } + \l_@@_tmpb_tl + { \tl_set:Nn \l_@@_tmpb_tl { 0 } } + \group_begin: + \prop_get:NnNT \l_@@_number_in_prop { exponent-sign } + \l_@@_tmpa_tl + { \tl_put_left:NV \l_@@_tmpb_tl \l_@@_tmpa_tl } + \exp_args:NNNV \group_end: + \tl_set:Nn \l_@@_tmpb_tl \l_@@_tmpb_tl + \tl_set:Nx \l_@@_tmpa_tl + { \l_@@_tmpa_tl { \l_@@_tmpb_tl } } + \exp_after:wN \@@_number_process_scientific_aux_i:nnn + \l_@@_tmpa_tl + } +} +\cs_new_protected:Npn \@@_number_process_scientific_aux_i:nnn #1#2#3 + { + \bool_set_true:N \l_@@_tmp_bool + \tl_map_inline:nn {#1#2} + { + \str_if_eq:nnF {##1} { 0 } + { + \bool_set_false:N \l_@@_tmp_bool + \tl_map_break: + } + } + \bool_if:NF \l_@@_tmp_bool + { \@@_number_process_scientific_aux_ii:nnn {#1} {#2} {#3} } + } +% \end{macrocode} +% The code here works on a loop, standardising the mantissa into the +% range \( 1 \le x < 10 \). +% \begin{macrocode} +\cs_new_protected:Npn + \@@_number_process_scientific_aux_ii:nnn #1#2#3 { + \int_compare:nNnTF { \tl_count:n {#1} } > 1 + { \@@_number_process_scientific_large:nnn {#1} {#2} {#3} } + { + \@@_number_if_zero:nTF {#1} + { + \@@_number_process_scientific_small:wn + #2 \q_stop {#3} + } + { + \bool_if:NTF \l_@@_process_engineering_bool + { \@@_number_process_scientific_engineering:nnn } + { \@@_number_process_scientific_store:nnn } + {#1} {#2} {#3} + } + + } +} +% \end{macrocode} +% A faster approach here is to use integer maths to do the digit move, +% but that runs into problems with the range available for the input. +% Instead, we use a loop to find the last digit. +% \begin{macrocode} +\cs_new_protected:Npn \@@_number_process_scientific_large:nnn #1#2#3 + { + \cs_set_protected:Npn \@@_number_process_scientific_large_loop:nNN + ##1##2##3 + { + \quark_if_recursion_tail_stop_do:Nn ##3 + { + \@@_number_process_scientific_aux_ii:nnn {##1} { ##2 #2 } + { #3 + 1 } + } + \@@_number_process_scientific_large_loop:nNN { ##1 ##2 } ##3 + } + \@@_number_process_scientific_large_loop:nNN { } #1 + \q_recursion_tail \q_recursion_stop + } +% \end{macrocode} +% For small numbers, the important digit is easy to find. +% \begin{macrocode} +\cs_new_protected:Npn + \@@_number_process_scientific_small:wn #1#2 \q_stop #3 + { \@@_number_process_scientific_aux_ii:nnn {#1} {#2} { #3 - 1 } } +% \end{macrocode} +% A tidy-up and store routine. +% \begin{macrocode} +\cs_new_protected:Npn + \@@_number_process_scientific_store:nnn #1#2#3 + { + \prop_put:Nnn \l_@@_number_in_prop { mantissa-integer } {#1} + \tl_if_empty:nTF {#2} + { + \prop_remove:Nn \l_@@_number_in_prop { mantissa-decimal } + \prop_remove:Nn \l_@@_number_in_prop + { mantissa-decimal-marker } + } + { + \prop_put:Nnn \l_@@_number_in_prop + { mantissa-decimal } {#2} + \prop_if_in:NnF \l_@@_number_in_prop + { mantissa-decimal-marker } + { + \prop_put:Nnn \l_@@_number_in_prop + { mantissa-decimal-marker } { . } + } + } + \int_compare:nNnTF {#3} = { 0 } + { + \prop_remove:Nn \l_@@_number_in_prop { exponent } + \prop_remove:Nn \l_@@_number_in_prop { exponent-sign } + \prop_remove:Nn \l_@@_number_in_prop { exponent-integer } + } + { + \prop_put:Nnn \l_@@_number_in_prop { exponent } { true } + \int_compare:nNnTF {#3} > { 0 } + { + \int_set:Nn \l_@@_tmp_int {#3} + \prop_put:NnV \l_@@_number_in_prop + { exponent-integer } \l_@@_tmp_int + \prop_remove:Nn \l_@@_number_in_prop { exponent-sign } + } + { + \int_set:Nn \l_@@_tmp_int { 0 - (#3) } + \prop_put:NnV \l_@@_number_in_prop + { exponent-integer } \l_@@_tmp_int + \prop_put:Nnn \l_@@_number_in_prop { exponent-sign } + { - } + } + } + } +% \end{macrocode} +% For engineering style, the exponent has to be a power of three. +% The fastest way to do this is by expansion, as the number of tokens +% is known. +% \begin{macrocode} +\cs_new_protected:Npn + \@@_number_process_scientific_engineering:nnn #1#2#3 + { + \use:c + { + @@_number_process_scientific_engineering_ + \int_compare:nNnTF {#3} < { 0 } + { + \int_case:nnF { \int_mod:nn { 0 - (#3) } { 3 } } + { + { 1 } { 2 } + { 2 } { 1 } + } + { 0 } + } + { \int_mod:nn {#3} { 3 } } + :nnn + } + {#1} {#2} {#3} + } +\cs_new_eq:cN + { @@_number_process_scientific_engineering_0:nnn } + \@@_number_process_scientific_store:nnn +\cs_new_protected:cpn + { @@_number_process_scientific_engineering_1:nnn } #1#2#3 + { + \tl_if_empty:nTF {#2} + { + \@@_number_process_scientific_store:nnn { #1 0 } { } + { #3 - 1 } + } + { + \use:c + { @@_number_process_scientific_engineering_1:nw } + {#1} #2 \q_stop {#3} + } + } +\cs_new_protected:cpn + { @@_number_process_scientific_engineering_1:nw } + #1#2#3 \q_stop #4 + { + \@@_number_process_scientific_store:nnn + {#1#2} {#3} { #4 - 1 } + } +\cs_new_protected:cpn + { @@_number_process_scientific_engineering_2:nnn } #1#2#3 + { + \tl_if_empty:nTF {#2} + { + \@@_number_process_scientific_store:nnn { #1 00 } { } + { #3 - 2 } + } + { + \use:c + { @@_number_process_scientific_engineering_2_i:nw } + {#1} #2 \q_stop {#3} + } + } +\cs_new_protected:cpn + { @@_number_process_scientific_engineering_2_i:nw } + #1#2#3 \q_stop #4 + { + \tl_if_empty:nTF {#3} + { + \@@_number_process_scientific_store:nnn { #1#2 0 } { } + { #4 - 2 } + } + { + \use:c + { @@_number_process_scientific_engineering_2_ii:nw } + {#1#2} #3 \q_stop {#4} + } + } +\cs_new_protected:cpn + { @@_number_process_scientific_engineering_2_ii:nw } + #1#2#3 \q_stop #4 + { + \@@_number_process_scientific_store:nnn { #1#2 } {#3} + { #4 - 2 } + } +% \end{macrocode} +%\end{macro} +%\end{macro} +% +%\begin{macro}{\@@_number_process_sign:} +%\begin{macro}{ +% \@@_number_process_sign_add:n , +% \@@_number_process_sign_plus:n +%} +%\begin{macro}{\c_@@_plus_tl} +% Sorting out signs consists of two parts: retaining a plus if necessary +% and adding an explicit sign. +% \begin{macrocode} +\cs_new_protected:Npn \@@_number_process_sign: { + \bool_if:NF \l_@@_process_plus_bool + { + \prop_if_in:NnTF \l_@@_number_in_prop { mantissa-sign } + { \@@_number_process_sign_plus:n { mantissa } } + { + \prop_if_in:NnT \l_@@_number_in_prop { complex-sign } + { + \prop_if_in:NnF \l_@@_number_in_prop { mantissa } + { \@@_number_process_sign_plus:n { complex } } + } + } + \prop_if_in:NnT \l_@@_number_in_prop { exponent-sign } + { \@@_number_process_sign_plus:n { exponent } } + } + \tl_if_empty:NF \l_@@_process_sign_tl + { + \@@_number_process_sign_add:n { mantissa } + \prop_if_in:NnTF \l_@@_number_in_prop { complex } + { \@@_number_process_sign_add:n { complex } } + } +} +% \end{macrocode} +% Adding a sign to an existing number needs a couple of to make sure +% there is a number to add to, and to see if there is a sign already. +% \begin{macrocode} +\cs_new_protected:Npn \@@_number_process_sign_add:n #1 { + \prop_if_in:NnF \l_@@_number_in_prop { #1 -sign } + { + \prop_if_in:NnF \l_@@_number_in_prop { #1 -had-sign } + { + \prop_get:NnN \l_@@_number_in_prop {#1} + \l_@@_tmpa_tl + \tl_if_empty:NTF \l_@@_tmpa_tl + { + \prop_put:NnV \l_@@_number_in_prop { sign } + \l_@@_process_sign_tl + } + { + \prop_put:NnV \l_@@_number_in_prop { #1 -sign } + \l_@@_process_sign_tl + } + } + } +} +% \end{macrocode} +% Holding onto a plus works very much in the same way as adding a sign: +% some quick tests and an assignment. Using a pre-defined token list is +% a speed-related choice: very slightly faster comparison. +% \begin{macrocode} +\cs_new_protected:Npn \@@_number_process_sign_plus:n #1 { + \prop_get:NnN \l_@@_number_in_prop { #1 -sign } + \l_@@_tmpa_tl + \tl_if_eq:NNT \c_@@_plus_tl \l_@@_tmpa_tl + { + \prop_remove:Nn \l_@@_number_in_prop { #1 -sign } + \prop_put:Nnn \l_@@_number_in_prop { #1 -had-sign } { true } + } +} +\tl_const:Nn \c_@@_plus_tl { + } +% \end{macrocode} +%\end{macro} +%\end{macro} +%\end{macro} +% +%\begin{macro}{\@@_number_process_uncertainty:} +%\begin{macro}{\@@_number_process_uncertainty_aux:n} +% There may be a need to expand uncertainties into a decimal and integer +% part. This is done here so that the core \texttt{in} code is faster. +% \begin{macrocode} +\cs_new_protected:Npn \@@_number_process_uncertainty: { + \clist_map_function:nN { mantissa , complex } + \@@_number_process_uncertainty_aux:n +} +\cs_new_protected:Npn + \@@_number_process_uncertainty_aux:n #1 { + \prop_if_in:NnT \l_@@_number_in_prop { #1 -uncertainty } + { + \prop_if_in:NnTF \l_@@_number_in_prop { #1 -decimal-marker } + { \@@_number_process_uncertainty_decimal:n {#1} } + { \@@_number_process_uncertainty_integer:n {#1} } + } +} +% \end{macrocode} +%\end{macro} +%\end{macro} +%\begin{macro}{\@@_number_process_uncertainty_decimal:n} +%\begin{macro}{\@@_number_process_uncertainty_count:nn} +% To deal with an error in the decimal part, care needs to be taken to +% correctly pad with zeros and also to allow for the possibility that +% the error crosses the decimal--integer boundary. +% \begin{macrocode} +\cs_new_protected:Npn + \@@_number_process_uncertainty_decimal:n #1 { + \@@_number_process_uncertainty_count:nn {#1} { decimal } + \@@_number_process_uncertainty_count:nn {#1} { uncertainty } + \tl_clear:N \l_@@_uncertainty_decimal_tl + \tl_clear:N \l_@@_uncertainty_integer_tl + \int_compare:nNnTF + { \l_@@_process_uncertainty_int } > + { \l_@@_process_decimal_int } + { \@@_number_process_uncertainty_separate: } + { \@@_number_process_uncertainty_pad: } + \tl_if_empty:NF \l_@@_uncertainty_integer_tl + { + \prop_put:NnV \l_@@_number_in_prop + { #1 -uncertainty-integer } + \l_@@_uncertainty_integer_tl + } + \prop_put:NnV \l_@@_number_in_prop { #1 -uncertainty-decimal } + \l_@@_uncertainty_decimal_tl + \prop_get:NnN \l_@@_number_in_prop { #1 -decimal-marker } + \l_@@_tmpa_tl + \prop_put:NnV \l_@@_number_in_prop + { #1 -uncertainty-decimal-marker } \l_@@_tmpa_tl +} +\cs_new_protected:Npn + \@@_number_process_uncertainty_count:nn #1#2 { + \prop_get:NnN \l_@@_number_in_prop { #1 - #2 } + \l_@@_tmpa_tl + \int_set:cn { l_@@_process_ #2 _int } + { \tl_count:N \l_@@_tmpa_tl } +} +% \end{macrocode} +%\end{macro} +%\end{macro} +%\begin{macro}{\@@_number_process_uncertainty_pad:} +% Uncertainty is short: add zeros. +% \begin{macrocode} +\cs_new_protected:Npn \@@_number_process_uncertainty_pad: { + \int_while_do:nNnn + { \l_@@_process_uncertainty_int } < + { \l_@@_process_decimal_int } + { + \tl_put_right:Nn \l_@@_uncertainty_decimal_tl {0} + \int_incr:N \l_@@_process_uncertainty_int + } + \tl_put_right:NV \l_@@_uncertainty_decimal_tl + \l_@@_tmpa_tl +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\@@_number_process_uncertainty_separate:} +%\begin{macro}{\@@_number_process_uncertainty_separate_aux:N} +% Find the integer--decimal boundary and work appropriately. +% \begin{macrocode} +\cs_new_protected:Npn + \@@_number_process_uncertainty_separate: { + \tl_map_function:NN \l_@@_tmpa_tl + \@@_number_process_uncertainty_separate_aux:N +} +\cs_new_protected:Npn + \@@_number_process_uncertainty_separate_aux:N #1 { + \int_compare:nNnTF + { \l_@@_process_uncertainty_int } > + { \l_@@_process_decimal_int } + { \tl_put_right:Nn \l_@@_uncertainty_integer_tl {#1} } + { \tl_put_right:Nn \l_@@_uncertainty_decimal_tl {#1} } + \int_decr:N \l_@@_process_uncertainty_int +} +% \end{macrocode} +%\end{macro} +%\end{macro} +%\begin{macro}{\@@_number_process_uncertainty_integer:n} +% Relatively easy: the uncertainty is in the integer part of the number, +% and so there is no need to generate zeros. +% \begin{macrocode} +\cs_new_protected:Npn + \@@_number_process_uncertainty_integer:n #1 { + \prop_get:NnN \l_@@_number_in_prop { #1 -uncertainty } + \l_@@_tmpa_tl + \prop_put:NnV \l_@@_number_in_prop { #1 -uncertainty-integer } + \l_@@_tmpa_tl +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\@@_number_process_zero_fill:} +%\begin{macro}{ +% \@@_number_process_zero_fill_aux:n , +% \@@_number_process_zero_fill_aux:nn +%} +% Checks for adding zeros to each component are carried out. The nesting +% here makes checking the appropriate flag a little more efficient. +% \begin{macrocode} +\cs_new_protected:Npn \@@_number_process_zero_fill: { + \@@_number_process_zero_fill_aux:n { integer } + \@@_number_process_zero_fill_aux:n { decimal } +} +\cs_new:Npn \@@_number_process_zero_fill_aux:n #1 { + \bool_if:cT { l_@@_process_ #1 _zero_bool } + { + \@@_number_process_zero_fill_aux:nn { mantissa } {#1} + \@@_number_process_zero_fill_aux:nn { complex } {#1} + \@@_number_process_zero_fill_aux:nn { exponent } {#1} + } +} +\cs_new_protected:Npn + \@@_number_process_zero_fill_aux:nn #1#2 { + \prop_if_in:NnT \l_@@_number_in_prop { #1 -decimal-marker } + { + \prop_if_in:NnF \l_@@_number_in_prop { #1 - #2 } + { \prop_put:Nnn \l_@@_number_in_prop { #1 - #2 } { 0 } } + } +} +% \end{macrocode} +%\end{macro} +%\end{macro} +% +% \begin{macro}{\@@_number_process_zero_to_integer:} +% \begin{macro}{\@@_number_process_zero_to_integer_aux:n} +% Look for a decimal part which is simply zero, and if found delete it. +% \begin{macrocode} +\cs_new_protected:Npn \@@_number_process_zero_to_integer: + { + \bool_if:NT \l_@@_zero_decimal_to_integer_bool + { + \@@_number_process_zero_to_integer_aux:n { mantissa } + \@@_number_process_zero_to_integer_aux:n { complex } + } + } +\cs_new_protected:Npn \@@_number_process_zero_to_integer_aux:n #1 + { + \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. The earlier formatting run will have reset the +% total number of units to zero, so that has to be recovered before +% doing the format a second time. +% \begin{macrocode} +\cs_new_protected:Npn \@@_number_exp_to_prefix: + { + \prop_set_eq:NN \l_@@_unit_prop \l_@@_unit_saved_prop + \prop_get:NnNT \l_@@_number_in_prop { exponent-integer } + \l_@@_tmpa_tl + { + \prop_get:NnNT \l_@@_number_in_prop { exponent-sign } + \l_@@_tmpb_tl + { \tl_put_left:NV \l_@@_tmpa_tl \l_@@_tmpb_tl } + \prop_if_in:NnT \l_@@_unit_prop { per-1 } + { + \tl_set:Nx \l_@@_tmpa_tl + { \int_eval:n { - \l_@@_tmpa_tl } } + } + \prop_get:NnNT \l_@@_unit_prop { prefix-1 } \l_@@_tmpb_tl + { + \prop_remove:Nn \l_@@_unit_prop { prefix-1 } + \prop_remove:Nn \l_@@_unit_prop { prefix-symbol-1 } + \prop_get:NVN \l_@@_prefix_forward_prop \l_@@_tmpb_tl + \l_@@_tmpb_tl + \tl_set:Nx \l_@@_tmpa_tl + { \int_eval:n { \l_@@_tmpa_tl + \l_@@_tmpb_tl } } + } + \prop_get:NnNT \l_@@_unit_prop { power-1 } \l_@@_tmpb_tl + { + \tl_set:Nx \l_@@_tmpa_tl + { \int_eval:n { \l_@@_tmpa_tl / \l_@@_tmpb_tl } } + } + \prop_get:NVNTF \l_@@_prefix_reverse_prop \l_@@_tmpa_tl + \l_@@_tmpb_tl + { + \prop_remove:Nn \l_@@_number_in_prop { exponent } + \use:c + { + @@_ \exp_after:wN \token_to_str:N \l_@@_tmpb_tl + _function:w + } + \prop_get:NnN \l_@@_unit_prop { total-units } \l_@@_tmpa_tl + \int_set:Nn \l_@@_unit_int \l_@@_tmpa_tl + \cs_set_eq:NN \@@_pm: \pm + \@@_unit_format: + \cs_set_eq:NN \pm \@@_pm: + } + { + \msg_error:nnx { siunitx } { non-convertible-exponent } + { \l_@@_tmpa_tl } + } + } + } +% \end{macrocode} +% \end{macro} +% +%\subsection{Formatting numbers for output} +% +% Getting numbers ready for printing requires the reconstruction of the +% number from the various parts processed earlier. Spaces and brackets +% are added back into the main numbers, as the various parts are also +% correctly formatted. The difference between the \texttt{in} and +% \texttt{out} store is that the later can include formatting such as +% hard spaces. +% +%\begin{macro}{\l_@@_number_out_prop} +% Like the \texttt{in} version! +% \begin{macrocode} +\prop_new:N \l_@@_number_out_prop +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{ +% \l_@@_group_sep_tl , +% \l_@@_output_decimal_tl +%} +% A couple of variables are declared here, as they need a little more +% work than just storage. +% \begin{macrocode} +\tl_new:N \l_@@_group_sep_tl +\tl_new:N \l_@@_output_decimal_tl +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\l_@@_complex_after_bool} +% A setting for where complex numbers go. +% \begin{macrocode} +\bool_new:N \l_@@_complex_after_bool +% \end{macrocode} +%\end{macro} +% +% \begin{variable} +% {\l_@@_group_decimal_bool, \l_@@_group_integer_bool} +% Used for grouping digits. +% \begin{macrocode} +\bool_new:N \l_@@_group_decimal_bool +\bool_new:N \l_@@_group_integer_bool +% \end{macrocode} +% \end{variable} +% +%\begin{macro}{ +% \l_@@_negative_bracket_bool , +% \l_@@_brackets_bool , +% \l_@@_bracket_close_tl , +% \l_@@_output_complex_copy_bool , +% \l_@@_output_decimal_copy_bool , +% \l_@@_exponent_base_tl , +% \l_@@_exponent_product_tl , +% \l_@@_group_min_int , +% \l_@@_negative_color_tl , +% \l_@@_bracket_open_tl , +% \l_@@_output_uncert_close_tl , +% \l_@@_output_complex_tl , +% \l_@@_output_exponent_tl , +% \l_@@_output_uncert_open_tl , +% \l_@@_uncert_sep_bool , +% \l_@@_tight_bool , +% \l_@@_uncert_sep_tl +%} +% Lots of settings, some used only for numbers, some more widely. +% \begin{macrocode} +\keys_define:nn { siunitx } { + bracket-negative-numbers .bool_set:N = + \l_@@_negative_bracket_bool , + bracket-numbers .bool_set:N = \l_@@_brackets_bool, + close-bracket .tl_set:N = \l_@@_bracket_close_tl, + complex-root-position .choice:, + complex-root-position + / after-number .code:n = + { \bool_set_true:N \l_@@_complex_after_bool } , + complex-root-position + / before-number .code:n = + { \bool_set_false:N \l_@@_complex_after_bool } , + copy-complex-root .bool_set:N = + \l_@@_output_complex_copy_bool, + copy-decimal-marker .bool_set:N = + \l_@@_output_decimal_copy_bool, + exponent-base .tl_set:N = \l_@@_exponent_base_tl, + exponent-product .tl_set:N = + \l_@@_exponent_product_tl, + group-decimal-digits .meta:n = { group-digits = decimal }, + group-digits .choice: , + group-digits / + decimal .code:n = + { + \bool_set_true:N \l_@@_group_decimal_bool + \bool_set_false:N \l_@@_group_integer_bool + }, + group-digits / + false .code:n = + { + \bool_set_false:N \l_@@_group_decimal_bool + \bool_set_false:N \l_@@_group_integer_bool + }, + group-digits / + integer .code:n = + { + \bool_set_false:N \l_@@_group_decimal_bool + \bool_set_true:N \l_@@_group_integer_bool + }, + group-digits / + true .code:n = + { + \bool_set_true:N \l_@@_group_decimal_bool + \bool_set_true:N \l_@@_group_integer_bool + }, + group-digits .default:n = true , + group-four-digits .choice:, + group-four-digits / + false .meta:n = { group-minimum-digits = 5 }, + group-four-digits / + true .meta:n = { group-minimum-digits = 4 }, + group-four-digits .default:n = true, + group-integer-digits .meta:n = { group-digits = integer }, + group-minimum-digits .int_set:N = \l_@@_group_min_int, + group-separator .code:n = + { \tl_set:Nn \l_@@_group_sep_tl { {#1} } }, + negative-color .tl_set:N = \l_@@_negative_color_tl, + open-bracket .tl_set:N = \l_@@_bracket_open_tl, + output-close-uncertainty .tl_set:N = + \l_@@_output_uncert_close_tl, + output-complex-root .tl_set:N = \l_@@_output_complex_tl , + output-decimal-marker .code:n = + { \tl_set:Nn \l_@@_output_decimal_tl { {#1} } }, + output-exponent-marker .tl_set:N = \l_@@_output_exponent_tl, + output-open-uncertainty .tl_set:N = + \l_@@_output_uncert_open_tl, + separate-uncertainty .bool_set:N = \l_@@_uncert_sep_bool, + tight-spacing .bool_set:N = \l_@@_tight_bool, + uncertainty-separator .tl_set:N = \l_@@_uncert_sep_tl, +} +\keys_set:nn { siunitx } + { + bracket-numbers = true , % ( + close-bracket = ) , + complex-root-position = after-number , + copy-decimal-marker = false , + exponent-base = 10 , + exponent-product = \times , + group-digits = true , + group-minimum-digits = 5 , + group-separator = \, , + open-bracket = ( , % ) ( + output-close-uncertainty = ) , + output-complex-root = \ensuremath { \mathrm { i } } , + output-decimal-marker = . , + output-open-uncertainty = ( % ) + } +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\@@_number_format:} +% The master control function for formatting output: the usual set up. +% The number is put back together in stages. +% \begin{macrocode} +\cs_new_protected:Npn \@@_number_format: { + \prop_if_empty:NF \l_@@_number_in_prop + { + \prop_clear:N \l_@@_number_out_prop + \@@_number_format_reassemble: + \@@_number_format_complex: + \@@_number_format_sign:n { mantissa } + \@@_number_format_sign:n { exponent } + \@@_number_format_relation: + \@@_number_format_color: + \@@_number_format_final: + } +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\@@_number_format_brackets:n} +%\begin{macro}{\@@_number_format_brackets_aux:n} +% There are various points at which brackets might be added to +% avoid ambiguity. The function here adds the appropriate tokens +% around whatever is in the supplied named store. +% \begin{macrocode} +\cs_new_protected:Npn \@@_number_format_brackets:n #1 { + \bool_if:NT \l_@@_brackets_bool + { + \prop_if_in:NnT \l_@@_number_out_prop { #1 -bracket } + { + \@@_number_format_brackets_aux:n {#1} + \prop_remove:Nn \l_@@_number_out_prop { #1 -bracket } + } + } +} +\cs_new_protected:Npn \@@_number_format_brackets_aux:n #1 { + \prop_get:NnNF \l_@@_number_out_prop { #1 -result } + \l_@@_tmpa_tl + { + \prop_get:NnN \l_@@_number_out_prop {#1} \l_@@_tmpa_tl + } + \tl_put_left:NV \l_@@_tmpa_tl \l_@@_bracket_open_tl + \tl_put_right:NV \l_@@_tmpa_tl \l_@@_bracket_close_tl + \str_if_eq:nnTF {#1} { result } + { \prop_put:NnV \l_@@_number_out_prop {#1} \l_@@_tmpa_tl } + { + \prop_put:NnV \l_@@_number_out_prop { #1 -result } + \l_@@_tmpa_tl + } +} +% \end{macrocode} +%\end{macro} +%\end{macro} +% +%\begin{macro}{\@@_number_format_color:} +%\begin{macro}{\@@_number_format_color_aux:n} +% If the mantissa is negative, then any colour for output might change. +% \begin{macrocode} +\cs_new_protected:Npn \@@_number_format_color: { + \tl_if_empty:NF \l_@@_negative_color_tl + { + \@@_number_format_color_aux:n { mantissa-sign } + \@@_number_format_color_aux:n { sign } + } +} +\cs_new_protected:Npn \@@_number_format_color_aux:n #1 { + \prop_get:NnNT \l_@@_number_in_prop {#1} \l_@@_tmpa_tl + { + \str_if_eq:VnT \l_@@_tmpa_tl { - } + { + \prop_put:NnV \l_@@_number_out_prop { color } + \l_@@_negative_color_tl + } + } +} +% \end{macrocode} +%\end{macro} +%\end{macro} +% +%\begin{macro}{\@@_number_format_complex:} +%\begin{macro}{ +% \@@_number_format_complex_aux:n , +% \@@_number_format_complex_aux: +%} +% The real and complex parts of each number are reassembled, with +% brackets if needed. +% \begin{macrocode} +\cs_new_protected:Npn \@@_number_format_complex: { + \prop_if_in:NnT \l_@@_number_in_prop { complex-root } + { + \prop_if_in:NnTF \l_@@_number_out_prop { complex } + { + \@@_number_format_brackets:n { complex } + \@@_number_format_complex_aux:n { complex } + \@@_number_format_complex_aux:n { complex-result } + \prop_if_in:NnT \l_@@_number_out_prop + { complex-uncertainty } + { + \@@_number_format_complex_aux:n + { complex-uncertainty } + } + } + { + \prop_put:NnV \l_@@_number_out_prop { complex } + \l_@@_output_complex_tl + } + \@@_number_format_join_complex: + } +} +\cs_new_protected:Npn \@@_number_format_complex_aux:n #1 { + \bool_if:NTF \l_@@_output_complex_copy_bool + { + \prop_get:NnN \l_@@_number_in_prop { complex-root } + \l_@@_tmpa_tl + } + { \tl_set_eq:NN \l_@@_tmpa_tl \l_@@_output_complex_tl } + \prop_get:NnN \l_@@_number_out_prop {#1} \l_@@_tmpb_tl + \bool_if:NTF \l_@@_complex_after_bool + { \tl_put_right:NV \l_@@_tmpb_tl \l_@@_tmpa_tl } + { \tl_put_left:NV \l_@@_tmpb_tl \l_@@_tmpa_tl } + \prop_put:NnV \l_@@_number_out_prop {#1} \l_@@_tmpb_tl +} +% \end{macrocode} +%\end{macro} +%\end{macro} +% +%\begin{macro}{ +% \@@_number_format_copy:n , +% \@@_number_format_copy:nn +%} +% Just copy across. +% \begin{macrocode} +\cs_new_protected:Npn \@@_number_format_copy:n #1 { + \prop_get:NnN \l_@@_number_in_prop {#1} \l_@@_tmpa_tl + \prop_put:NnV \l_@@_number_out_prop {#1} \l_@@_tmpa_tl +} +\cs_new_protected:Npn \@@_number_format_copy:nn #1#2 { + \prop_get:NnN \l_@@_number_out_prop {#1} \l_@@_tmpa_tl + \prop_put:NnV \l_@@_number_out_prop {#2} \l_@@_tmpa_tl +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\@@_number_format_final:} +% For numbers which do not contain an exponent, the mantissa result is +% simply copied to the final output position. On the other hand, for +% exponents there are further checks, which are handed off to dedicated +% functions. There is also a check for complex numbers with no real +% part, which needs to be \enquote{copied} to the standard result +% slot. +% \begin{macrocode} +\cs_new_protected:Npn \@@_number_format_final: { + \prop_if_in:NnT \l_@@_number_out_prop { complex } + { + \prop_if_in:NnF \l_@@_number_out_prop { mantissa-result } + { + \@@_number_format_copy:nn { complex } + { mantissa-result } + } + } + \prop_if_in:NnTF \l_@@_number_out_prop { exponent } + { + \@@_number_format_final_exponent: + \prop_if_in:NnTF \l_@@_number_out_prop { mantissa-result } + { \@@_number_format_final_combined: } + { \@@_number_format_final_exponent_only: } + } + { \@@_number_format_copy:nn { mantissa-result } { result } } + \prop_if_in:NnT \l_@@_number_out_prop { mantissa-bracket } + { + \prop_put:Nnn \l_@@_number_out_prop { result-bracket } + { true } + \prop_remove:Nn \l_@@_number_out_prop { mantissa-bracket } + } + \prop_if_in:NnT \l_@@_number_out_prop { comparator } + { + \@@_number_format_brackets:n { result } + \prop_get:NnN \l_@@_number_out_prop { comparator } + \l_@@_tmpa_tl + \prop_get:NnN \l_@@_number_out_prop { result } + \l_@@_tmpb_tl + \tl_set:Nx \l_@@_tmpa_tl + { + \exp_not:N \mathord + \exp_not:V \l_@@_tmpa_tl + \exp_not:V \l_@@_tmpb_tl + } + \prop_put:NnV \l_@@_number_out_prop { result } + \l_@@_tmpa_tl + } +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\@@_number_format_final_combined:} +% When there is both a mantissa and an exponent, the mantissa is +% combined with the product sign before adding the exponent part on. +% The combined result is then stored. The marker +% \texttt{result-bracket-exponent} indicates that the number needs +% brackets due to the exponent part, but not in other cases. +% \begin{macrocode} +\cs_new_protected:Npn \@@_number_format_final_combined: { + \@@_number_format_brackets:n { mantissa } + \prop_get:NnN \l_@@_number_out_prop { mantissa-result } + \l_@@_tmpa_tl + \tl_if_empty:NT \l_@@_output_exponent_tl + { + \tl_put_right:Nx \l_@@_tmpa_tl + { + \exp_not:N \ensuremath + { + \bool_if:NTF \l_@@_tight_bool + { { \exp_not:V \l_@@_exponent_product_tl } } + { { } \exp_not:V \l_@@_exponent_product_tl { } } + } + } + } + \prop_get:NnN \l_@@_number_out_prop { exponent-result } + \l_@@_tmpb_tl + \tl_put_right:NV \l_@@_tmpa_tl \l_@@_tmpb_tl + \prop_put:NnV \l_@@_number_out_prop { result } + \l_@@_tmpa_tl + \prop_put:Nnn \l_@@_number_out_prop + { result-bracket-exponent } { true } +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\@@_number_format_final_exponent:} +% When there is an exponent, the base always needs to be added to the +% front of the number itself. The number must be superscripted, of +% course. +% \begin{macrocode} +\cs_new_protected:Npn \@@_number_format_final_exponent: { + \prop_get:NnN \l_@@_number_out_prop { exponent } + \l_@@_tmpa_tl + \tl_if_empty:NTF \l_@@_output_exponent_tl + { + \tl_set:Nx \l_@@_tmpa_tl + { ^ { \exp_not:V \l_@@_tmpa_tl } } + \tl_put_left:NV \l_@@_tmpa_tl \l_@@_exponent_base_tl + } + { + \tl_set:Nx \l_@@_tmpa_tl + { + \exp_not:V \l_@@_output_exponent_tl + \exp_not:N \mathord + \exp_not:V \l_@@_tmpa_tl + } + } + \prop_put:NnV \l_@@_number_out_prop { exponent-result } + \l_@@_tmpa_tl +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\@@_number_format_final_exponent_only:} +% When there is only an exponent, a check must be made for a +% sign in the mantissa part. If there is one, it is copied across. +% \begin{macrocode} +\cs_new_protected:Npn + \@@_number_format_final_exponent_only: { + \prop_get:NnNT \l_@@_number_in_prop { mantissa-sign } + \l_@@_tmpa_tl + { + \prop_get:NnN \l_@@_number_out_prop { exponent-result } + \l_@@_tmpb_tl + \@@_tl_put_left_math:NV \l_@@_tmpb_tl + \l_@@_tmpa_tl + \prop_put:NnV \l_@@_number_out_prop { exponent-result } + \l_@@_tmpb_tl + } + \@@_number_format_copy:nn { exponent-result } { result } +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\@@_number_format_group:n} +%\begin{macro}{\@@_number_format_group_aux:nn} +% Grouping digits only happens if there are no symbols in the input, and +% of course if grouping has been requested. +% \begin{macrocode} +\cs_new_protected:Npn \@@_number_format_group:n #1 { + \@@_number_format_group_aux:nn {#1} { integer } + \@@_number_format_group_aux:nn {#1} { decimal } + \prop_if_in:NnTF \l_@@_number_out_prop { #1 -integer } + { \@@_number_format_copy:nn { #1 -integer } {#1} } + { \tl_clear:N \l_@@_tmpa_tl } + \prop_get:NnNT \l_@@_number_in_prop { #1 -decimal-marker } + \l_@@_tmpb_tl + { + \bool_if:NTF \l_@@_output_decimal_copy_bool + { \tl_set:Nx \l_@@_tmpb_tl { { \l_@@_tmpb_tl } } } + { + \tl_set_eq:NN \l_@@_tmpb_tl + \l_@@_output_decimal_tl + } + \tl_put_right:NV \l_@@_tmpa_tl \l_@@_tmpb_tl + \prop_put:NnV \l_@@_number_out_prop { #1 -decimal-marker } + \l_@@_tmpb_tl + \prop_get:NnNF \l_@@_number_out_prop { #1 -decimal } + \l_@@_tmpb_tl + { \tl_clear:N \l_@@_tmpb_tl } + \tl_put_right:NV \l_@@_tmpa_tl \l_@@_tmpb_tl + \prop_put:NnV \l_@@_number_out_prop {#1} \l_@@_tmpa_tl + } +} +\cs_new_protected:Npn \@@_number_format_group_aux:nn #1#2 { + \prop_if_in:NnT \l_@@_number_in_prop { #1 - #2 } + { + \bool_if:cTF { l_@@_group_ #2 _bool } + { \@@_number_format_group:nn {#1} {#2} } + { \@@_number_format_copy:n { #1 - #2 } } + } +} +% \end{macrocode} +%\end{macro} +%\end{macro} +% \begin{macro}{\@@_number_format_group:nn} +% The idea here is that grouping is only needed for numbers with sufficient +% digits: this is done simply by counting up all of the digits. +% \begin{macrocode} +\cs_new_protected:Npn \@@_number_format_group:nn #1#2 + { + \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}{\@@_number_format_group_decimal_aux:} +% Using the \enquote{keep everything on the stack} approach, relatively +% simple recursion is needed. This trick is taken more or less directly +% from \pkg{numprint}. +% \begin{macrocode} +\cs_new_protected:Npn \@@_number_format_group_decimal: { + \tl_if_empty:NF \l_@@_tmpa_tl + { + \exp_after:wN \@@_number_format_group_decimal_aux:NNNN + \l_@@_tmpa_tl { } { } { } + } +} +\cs_new_protected:Npn \@@_number_format_group_decimal_aux:NNNN + #1#2#3#4 { + \tl_if_empty:nTF {#2} + { \tl_put_right:Nn \l_@@_tmpb_tl {#1} } + { + \tl_if_empty:nTF {#3} + { \tl_put_right:Nn \l_@@_tmpb_tl { #1 #2 } } + { + \tl_put_right:Nn \l_@@_tmpb_tl { #1 #2 #3 } + \tl_if_empty:nF {#4} + { + \tl_put_right:NV \l_@@_tmpb_tl \l_@@_group_sep_tl + \@@_number_format_group_decimal_aux:NNNN #4 + } + } + } +} +% \end{macrocode} +%\end{macro} +%\end{macro} +%\begin{macro}{\@@_number_format_group_integer:} +%\begin{macro}{ +% \@@_number_format_group_integer_setup:n , +% \@@_number_format_group_integer_setup:V , +% \@@_number_format_group_integer_setup_aux:NNNN , +% \@@_number_format_group_integer_aux:NNNN +%} +% By keeping everything on the stack, recursion can occur quite +% efficiently here. +% \begin{macrocode} +\cs_new_protected:Npn \@@_number_format_group_integer: { + \tl_if_empty:NF \l_@@_tmpa_tl + { + \@@_number_format_group_integer_setup:V \l_@@_tmpa_tl + } +} +\cs_new_protected:Npn \@@_number_format_group_integer_setup:n #1 { + \@@_number_format_group_integer_setup_aux:NNNN + { } #1 { } { } { } +} +\cs_generate_variant:Nn \@@_number_format_group_integer_setup:n + { V } +\cs_new_protected:Npn + \@@_number_format_group_integer_setup_aux:NNNN #1#2#3#4 { + \tl_if_empty:nTF {#2} + { \@@_number_format_group_integer_aux:NNNN #1 \q_nil } + { + \tl_if_empty:nTF {#3} + { + \@@_number_format_group_integer_aux:NNNN { } { } #1#2 + \q_nil + } + { + \tl_if_empty:nTF {#4} + { + \@@_number_format_group_integer_aux:NNNN { } #1#2#3 + \q_nil + } + { + \@@_number_format_group_integer_setup_aux:NNNN + {#1#2#3#4} + } + } + } +} +\cs_new_protected:Npn + \@@_number_format_group_integer_aux:NNNN #1#2#3#4 { + \tl_put_right:Nn \l_@@_tmpb_tl {#1#2#3} + \quark_if_nil:nF {#4} + { + \tl_put_right:NV \l_@@_tmpb_tl \l_@@_group_sep_tl + \@@_number_format_group_integer_aux:NNNN #4 + } +} +% \end{macrocode} +%\end{macro} +%\end{macro} +% +%\begin{macro}{\@@_number_format_join_complex:} +% For adding the complex part to the main part of a number. +% \begin{macrocode} +\cs_new_protected:Npn \@@_number_format_join_complex: { + \@@_number_format_sign_complex: + \prop_if_in:NnT \l_@@_number_out_prop { mantissa } + { + \@@_number_format_brackets:n { mantissa } + \prop_get:NnN \l_@@_number_out_prop { mantissa-result } + \l_@@_tmpa_tl + \prop_get:NnNF \l_@@_number_out_prop { complex-result } + \l_@@_tmpb_tl + { + \prop_get:NnN \l_@@_number_out_prop { complex } + \l_@@_tmpb_tl + } + \tl_put_right:NV \l_@@_tmpa_tl \l_@@_tmpb_tl + \prop_put:NnV \l_@@_number_out_prop { mantissa-result } + \l_@@_tmpa_tl + \prop_put:Nnn \l_@@_number_out_prop { mantissa-bracket } + { true } + } +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{ +% \@@_number_format_join_uncert: , +% \@@_number_format_join_uncert:n +%} +%\begin{macro}{\@@_number_format_join_uncert_pm:N} +% For adding separated uncertainties to the main part of a number. +% \begin{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}{ +% \@@_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}{ +% \@@_number_format_uncertainty_joined:n , +% \@@_number_format_uncertainty_sep:n +%} +% Uncertainty output varies depending on whether there is a need to +% separate the error form the number in the output. +% \begin{macrocode} +\cs_new_protected:Npn \@@_number_format_uncertainty:n #1 { + \prop_if_in:NnTF \l_@@_number_in_prop { #1 -uncertainty } + { + \bool_if:NTF \l_@@_uncert_sep_bool + { \@@_number_format_uncertainty_sep:n {#1} } + { \@@_number_format_uncertainty_joined:n {#1} } + \@@_number_format_join_uncert: + } + { \@@_number_format_copy:nn {#1} { #1 -result } } +} +\cs_new_protected:Npn + \@@_number_format_uncertainty_joined:n #1 { + \prop_get:NnN \l_@@_number_in_prop { #1 -uncertainty } + \l_@@_tmpa_tl + \prop_remove:Nn \l_@@_number_in_prop { #1 -uncertainty } + \tl_put_left:NV \l_@@_tmpa_tl \l_@@_output_uncert_open_tl + \tl_put_left:NV \l_@@_tmpa_tl \l_@@_uncert_sep_tl + \tl_put_right:NV \l_@@_tmpa_tl \l_@@_output_uncert_close_tl + \prop_get:NnN \l_@@_number_out_prop {#1} \l_@@_tmpb_tl + \tl_put_right:NV \l_@@_tmpb_tl \l_@@_tmpa_tl + \prop_put:NnV \l_@@_number_out_prop {#1} \l_@@_tmpb_tl +} +\cs_new_protected:Npn + \@@_number_format_uncertainty_sep:n #1 { + \prop_if_in:NnT \l_@@_number_out_prop { #1 -integer } + { + \prop_if_in:NnF \l_@@_number_out_prop + { #1 -uncertainty-integer } + { + \prop_put:Nnn \l_@@_number_out_prop + { #1 -uncertainty-integer } { 0 } + } + } + \@@_number_format_group:n { #1 -uncertainty } + \prop_put:NnV \l_@@_number_out_prop { #1 -uncertainty } + \l_@@_tmpa_tl +} +% \end{macrocode} +%\end{macro} +%\end{macro} +% +%\subsection{Numerical output} +% +% The outer level of number processing for actually printing things. +% +%\begin{macro}{ +% \l_@@_number_out_tl , +% \l_@@_number_out_saved_tl +%} +% The final result, plus a version for loops. +% \begin{macrocode} +\tl_new:N \l_@@_number_out_tl +\tl_new:N \l_@@_number_out_saved_tl +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\l_@@_number_fraction_tl} +% Fractions need to be build separately, so that there is no problem +% with stack order. +% \begin{macrocode} +\tl_new:N \l_@@_number_fraction_tl +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\l_@@_number_compound_bool} +% To help with brackets. +% \begin{macrocode} +\bool_new:N \l_@@_number_compound_bool +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\l_@@_quotient_mode_tl} +% The action for quotients is stored as a token list variable. +% \begin{macrocode} +\tl_new:N \l_@@_quotient_mode_tl +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\@@_fraction:nn} +% The function used for fractions should be stored here. +% \begin{macrocode} +\cs_new_protected:Npn \@@_fraction:nn { } +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{ +% \l_@@_output_quotient_tl , +% \l_siunix_number_parse_bool +%} +% Some options related to numbers at the output stage. +% \begin{macrocode} +\keys_define:nn { siunitx } { + fraction-function .code:n = + { \cs_set_protected:Npn \@@_fraction:nn {#1} }, + output-product .tl_set:N = \l_@@_output_product_tl, + output-quotient .tl_set:N = \l_@@_output_quotient_tl, + parse-numbers .bool_set:N = \l_@@_number_parse_bool, + quotient-mode .choice:, + quotient-mode / fraction .code:n = + { \tl_set:Nn \l_@@_quotient_mode_tl { fraction } }, + quotient-mode / symbol .code:n = + { \tl_set:Nn \l_@@_quotient_mode_tl { symbol } }, +} +\keys_set:nn { siunitx } { + fraction-function = \frac , + output-product = \times , + output-quotient = / , + parse-numbers = true , + quotient-mode = symbol +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{ +% \@@_number_output:n , +% \@@_number_output:V +%} +% The number output system simply sets up for the combined number and +% unit system. +% \begin{macrocode} +\cs_new_protected:Npn \@@_number_output:n #1 { + \tl_clear:N \l_@@_unit_tl + \tl_clear:N \l_@@_preunit_tl + \@@_combined_output:n {#1} +} +\cs_generate_variant:Nn \@@_number_output:n { V } +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\@@_number_output_bracket:} +% Compound numbers may need brackets adding. +% \begin{macrocode} +\cs_new_protected:Npn \@@_number_output_bracket: { + \bool_if:NF \l_@@_error_bool + { + \bool_if:NT \l_@@_number_compound_bool + { \@@_number_format_brackets:n { result } } + } +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\@@_number_output_color:} +% If a colour needs to be set, it is recovered here and put into the +% appropriate place. +% \begin{macrocode} +\cs_new_protected:Npn \@@_number_output_color: { + \prop_if_in:NnT \l_@@_number_out_prop { color } + { + \prop_get:NnN \l_@@_number_out_prop { color } + \l_@@_number_color_tl + } +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{ +% \@@_number_output_parse:n , +% \@@_number_output_parse:V +%} +%\begin{macro}{\@@_number_output_parse_aux:} +% The parsing system just has to check if there are multiple parts to +% worry about. +% \begin{macrocode} +\cs_new_protected:Npn \@@_number_output_parse:n #1 { + \@@_number_preprocess:n {#1} + \bool_if:NF \l_@@_error_bool + { + \tl_if_empty:NTF \l_@@_number_multi_tl + { \@@_number_output_parse_aux: } + { + \use:c + { @@_number_output_ \l_@@_number_multi_tl : } + } + } +} +\cs_generate_variant:Nn \@@_number_output_parse:n { V } +% \end{macrocode} +% There are a few additional tests for printing partwise, as this is +% only needed if there are brackets to add and these are not due to +% an exponent. The test for an exponent is needed as this must force +% the units to come at the end of the number, and there then have to +% be brackets in the output if there are any separate parts. +% \begin{macrocode} +\cs_new_protected:Npn \@@_number_output_parse_aux: { + \@@_number_in_parse:V \l_@@_number_arg_tl + \bool_if:NF \l_@@_error_bool + { + \@@_number_process: + \@@_number_format: + \@@_number_output_color: + \bool_if:NTF \l_@@_brackets_bool + { \@@_number_output_single: } + { + \prop_if_in:NnTF \l_@@_number_out_prop + { result-bracket } + { \@@_number_output_parts: } + { \@@_number_output_single: } + } + } +} +% \end{macrocode} +%\end{macro} +%\end{macro} +% +%\begin{macro}{\@@_number_output_parts:} +%\begin{macro}{ +% \@@_number_output_parts_aux: , +% \@@_number_output_parts_aux:n , +% \@@_number_output_parts_print:n +%} +% Printing numbers by parts is necessary when there are units to +% repeat. That means doing things that have already been done by the +% number formatter again. +% \begin{macrocode} +\cs_new_protected:Npn \@@_number_output_parts: { + \bool_lazy_and:nnTF + { \tl_if_empty_p:N \l_@@_pre_unit_tl } + { \tl_if_empty_p:N \l_@@_unit_tl } + { \@@_number_output_single: } + { \@@_number_output_parts_aux: } +} +\cs_new_protected:Npn \@@_number_output_parts_aux: { + \bool_if:NTF \l_@@_multi_repeat_bool + { + \prop_if_in:NnT \l_@@_number_out_prop { mantissa-result } + { + \@@_number_output_parts_aux:n { mantissa } + \@@_number_output_parts_aux:n { complex } + } + \prop_get:NnNT \l_@@_number_out_prop { exponent-result } + \l_@@_tmpa_tl + { + \prop_if_in:NnT \l_@@_number_out_prop { mantissa-result } + { + \tl_put_left:Nx \l_@@_tmpa_tl + { + \exp_not:N \ensuremath + { + \bool_if:NTF \l_@@_tight_bool + { { \exp_not:V \l_@@_exponent_product_tl } } + { { } \exp_not:V \l_@@_exponent_product_tl { } } + } + } + \prop_put:NnV \l_@@_number_out_prop { exponent } + \l_@@_tmpa_tl + } + \@@_number_output_parts_print:n { exponent } + } + } + { \@@_number_output_single: } +} +\cs_new_protected:Npn \@@_number_output_parts_aux:n #1 { + \prop_if_in:NnT \l_@@_number_out_prop {#1} + { \@@_number_output_parts_print:n {#1} } + \prop_if_in:NnT \l_@@_number_out_prop { #1 -uncertainty } + { + \bool_if:NTF \l_@@_tight_bool + { \@@_print:nn { number } { \ensuremath { { \pm } } } } + { \@@_print:nn { number } { \ensuremath { { } \pm { } } } } + \@@_number_output_parts_print:n { #1 -uncertainty } + } +} +\cs_new_protected:Npn \@@_number_output_parts_print:n #1 { + \@@_unit_output_pre_print: + \prop_get:NnN \l_@@_number_out_prop {#1} \l_@@_tmpa_tl + \@@_print:nV { number } \l_@@_tmpa_tl + \@@_unit_output_print: +} +% \end{macrocode} +%\end{macro} +%\end{macro} +% +%\begin{macro}{\@@_number_output_product:} +% For products, there may need to be the addition of brackets if there +% are units about. When not repeating units, some work has to be done to +% print everything correctly. The extra group here is necessary +% otherwise looping will delete the units entirely! +% \begin{macrocode} +\cs_new_protected:Npn \@@_number_output_product: { + \bool_if:NTF \l_@@_product_brackets_bool + { + \bool_lazy_and:nnTF + { \tl_if_empty_p:N \l_@@_pre_unit_tl } + { \tl_if_empty_p:N \l_@@_unit_tl } + { \@@_number_output_product_aux: } + { \@@_number_output_product_brackets: } + } + { + \bool_if:NTF \l_@@_product_repeat_bool + { \@@_number_output_product_aux: } + { + \@@_unit_output_pre_print: + \tl_set_eq:NN \l_@@_unit_saved_tl \l_@@_unit_tl + \tl_clear:N \l_@@_pre_unit_tl + \tl_clear:N \l_@@_unit_tl + \group_begin: + \@@_number_output_product_aux: + \group_end: + \tl_set_eq:NN \l_@@_unit_tl \l_@@_unit_saved_tl + \@@_unit_output_print: + } + } +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\@@_number_output_product_brackets:} +% When printing products that have to be bracketed, there is a need to +% shuffle the units about a bit. +% \begin{macrocode} +\cs_new_protected:Npn \@@_number_output_product_brackets: { + \@@_unit_output_pre_print: + \@@_print:nV { number } \l_@@_bracket_open_tl + \nobreak + \tl_set_eq:NN \l_@@_unit_saved_tl \l_@@_unit_tl + \tl_clear:N \l_@@_pre_unit_tl + \tl_clear:N \l_@@_unit_tl + \@@_number_output_product_aux: + \nobreak + \tl_set_eq:NN \l_@@_unit_tl \l_@@_unit_saved_tl + \@@_print:nV { number } \l_@@_bracket_close_tl + \@@_unit_output_print: +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\@@_number_output_product_aux:} +% Printing the products needs a looping function. +% \begin{macrocode} +\cs_new_protected:Npn \@@_number_output_product_aux: { + \bool_set_true:N \l_@@_number_compound_bool + \@@_number_preprocess:V \l_@@_number_arg_tl + \bool_if:NF \l_@@_error_bool + { + \tl_if_empty:NTF \l_@@_number_multi_tl + { \@@_number_output_parse_aux: } + { \@@_number_output_quotient: } + \tl_if_empty:NF \l_@@_number_next_tl + { + \bool_if:NTF \l_@@_tight_bool + { + \@@_print:nn { number } + { \ensuremath { \l_@@_output_product_tl } } + } + { + \@@_print:nn { number } + { \ensuremath { { } \l_@@_output_product_tl { } } } + } + \@@_number_output_parse:V \l_@@_number_next_tl + } + } +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\@@_number_output_quotient:} +% For quotients, there are two options. +% \begin{macrocode} +\cs_new_protected:Npn \@@_number_output_quotient: { + \use:c + { @@_number_output_quotient_ \l_@@_quotient_mode_tl : } +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\@@_number_output_quotient_fraction:} +% For fraction output, there are quite a lot of braces to construct, +% unfortunately. +% \begin{macrocode} +\cs_new_protected:Npn \@@_number_output_quotient_fraction: { + \bool_set_false:N \l_@@_number_compound_bool + \@@_number_output_quotient_aux_i: + \tl_set:Nx \l_@@_number_out_tl + { { \exp_not:V \l_@@_number_numerator_tl } } + \tl_set:Nx \l_@@_tmpa_tl + { { \exp_not:V \l_@@_number_denominator_tl } } + \tl_put_right:NV \l_@@_number_out_tl \l_@@_tmpa_tl + \tl_put_left:Nn \l_@@_number_out_tl { \@@_fraction:nn } + \tl_set:Nx \l_@@_number_out_tl + { + \exp_not:N \ensuremath + { \exp_not:V \l_@@_number_out_tl } + } + \@@_number_output_single_aux: +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\@@_number_output_quotient_symbol:} +% If a symbol is used for the division, the build process is less +% complex. +% \begin{macrocode} +\cs_new_protected:Npn \@@_number_output_quotient_symbol: { + \bool_set_true:N \l_@@_number_compound_bool + \@@_number_output_quotient_aux_i: + \tl_set_eq:NN \l_@@_number_out_tl + \l_@@_number_numerator_tl + \tl_put_right:NV \l_@@_number_out_tl \l_@@_output_quotient_tl + \tl_put_right:NV \l_@@_number_out_tl + \l_@@_number_denominator_tl + \@@_number_output_single_aux: +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{ +% \@@_number_output_quotient_aux_i: , +% \@@_number_output_quotient_aux_ii: +%} +% The two parts of the number are parsed and formatted. +% \begin{macrocode} +\cs_new_protected:Npn \@@_number_output_quotient_aux_i: { + \@@_number_in_parse:V \l_@@_number_numerator_tl + \@@_number_output_quotient_aux_ii: + \@@_number_output_color: + \prop_if_in:NnT \l_@@_number_out_prop { complex } + { + \prop_if_in:NnT \l_@@_number_out_prop { mantissa } + { + \prop_put:Nnn \l_@@_number_out_prop + { result-bracket } { true } + \@@_number_format_brackets:n { result } + } + } + \prop_get:NnN \l_@@_number_out_prop { result } + \l_@@_number_numerator_tl + \@@_number_in_parse:V \l_@@_number_denominator_tl + \@@_number_output_quotient_aux_ii: + \prop_if_in:NnT \l_@@_number_out_prop + { result-bracket-exponent } + { + \prop_put:Nnn \l_@@_number_out_prop { result-bracket } + { true } + } + \@@_number_output_bracket: + \prop_get:NnN \l_@@_number_out_prop { result } + \l_@@_number_denominator_tl +} +\cs_new_protected:Npn \@@_number_output_quotient_aux_ii: { + \@@_number_process: + \@@_number_format: +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\@@_number_output_single:} +%\begin{macro}{\@@_number_output_single_aux:} +% Printing a number with no multiple parts is easy. There is a check for +% any units, which if present may force the number to have brackets +% added. there is then simply a short run to print the units and number. +% The test for bracketing numbers does not happen if there is an +% exponent: if there is, any other parts will already be bracketed and +% mathematically there is no need for brackets at this point. +% \begin{macrocode} +\cs_new_protected:Npn \@@_number_output_single: { + \bool_lazy_and:nnF + { \tl_if_empty_p:N \l_@@_pre_unit_tl } + { \tl_if_empty_p:N \l_@@_unit_tl } + { + \prop_if_in:NnF \l_@@_number_out_prop { exponent } + { \@@_number_format_brackets:n { result } } + } + \@@_number_output_bracket: + \prop_get:NnN \l_@@_number_out_prop { result } + \l_@@_number_out_tl + \@@_number_output_single_aux: +} +\cs_new_protected:Npn \@@_number_output_single_aux: { + \@@_unit_output_pre_print: + \quark_if_no_value:NTF \l_@@_number_out_tl + { \tl_clear:N \l_@@_number_unit_product_tl } + { \@@_print:nV { number } \l_@@_number_out_tl } + \@@_unit_output_print: +} +% \end{macrocode} +%\end{macro} +%\end{macro} +% +%\subsection{Angles} +% +% Angles are a special case of numbers for two reasons. First, there +% is always a unit, which is known in advance. Second, there are two +% possible input syntaxes, "\ang{1.23}" and "\ang{1;2;3}". Both need +% to be handled correctly. +% +%\begin{macro}{ +% \l_@@_angle_degree_space_bool , +% \l_@@_angle_minute_space_bool +%} +% The need for spaces between parts of an arc needs to be accommodated: +% this is achieved by flagging up the need for such spaces using two +% switches. +% \begin{macrocode} +\bool_new:N \l_@@_angle_degree_space_bool +\bool_new:N \l_@@_angle_minute_space_bool +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{ +% \l_@@_angle_marker_box , +% \l_@@_angle_unit_box , +% \l_@@_angle_marker_dim , +% \l_@@_angle_unit_dim +%} +% When creating astronomy-style angles, the decimal marker and angle +% symbol have to be boxed up and measured. +% \begin{macrocode} +\box_new:N \l_@@_angle_marker_box +\box_new:N \l_@@_angle_unit_box +\dim_new:N \l_@@_angle_marker_dim +\dim_new:N \l_@@_angle_unit_dim +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{ +% \l_@@_angle_degree_prop , +% \l_@@_angle_minute_prop , +% \l_@@_angle_second_prop +%} +% As there are potentially three numbers to parse, three properly lists +% are made available to hold the results. This allows the code to be +% generalised, with only the name of the storage area varying. +% \begin{macrocode} +\prop_new:N \l_@@_angle_degree_prop +\prop_new:N \l_@@_angle_minute_prop +\prop_new:N \l_@@_angle_second_prop +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{ +% \l_@@_angle_degree_zero_bool , +% \l_@@_angle_minute_zero_bool , +% \l_@@_angle_second_zero_bool , +% \l_@@_angle_arc_separator_tl , +% \l_@@_angle_astronomy_bool , +% \l_@@_angle_unit_product_tl +%} +% The angle-specific options are created here. +% \begin{macrocode} +\keys_define:nn { siunitx } { + add-arc-degree-zero .bool_set:N = + \l_@@_angle_degree_zero_bool , + add-arc-minute-zero .bool_set:N = + \l_@@_angle_minute_zero_bool , + add-arc-second-zero .bool_set:N = + \l_@@_angle_second_zero_bool , + angle-symbol-over-decimal .bool_set:N = + \l_@@_angle_astronomy_bool , + arc-separator .tl_set:N = + \l_@@_angle_arc_separator_tl , + number-angle-product .tl_set:N = + \l_@@_angle_unit_product_tl , + number-angle-separator .tl_set:N = + \l_@@_angle_unit_product_tl , +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\@@_angle_output:nnn} +%\begin{macro}{\@@_angle_output_aux:nnn} +% The input will have been split up by \pkg{xparse}, and so the various +% possible inputs can be picked up. To keep to a minimal route through +% the code, a decimal angle is simply treated like an arc, but with +% any zero-filling disabled. +% \begin{macrocode} +\cs_new_protected:Npn \@@_angle_output:nnn #1#2#3 { + \@@_angle_init: + \IfNoValueTF {#2} + { + \bool_set_false:N \l_@@_angle_minute_zero_bool + \bool_set_false:N \l_@@_angle_second_zero_bool + \@@_angle_output_aux:nnn {#1} { } { } + } + { + \IfNoValueTF {#3} + { \@@_error:nx { invalid-arc-format } { #1 ; #2 } } + { \@@_angle_output_aux:nnn {#1} {#2} {#3} } + } +} +\cs_new_protected:Npn \@@_angle_output_aux:nnn #1#2#3 { + \tl_if_empty:nTF { #1#2#3 } + { \@@_error:n { empty-arc } } + { + \bool_if:NTF \l_@@_number_parse_bool + { \@@_angle_parse:nnn {#1} {#2} {#3} } + { \@@_angle_direct:nnn {#1} {#2} {#3} } + } +} +% \end{macrocode} +%\end{macro} +%\end{macro} +% +%\begin{macro}{\@@_angle_init:} +% The usual separation of initial storage resets. +% \begin{macrocode} +\cs_new_protected:Npn \@@_angle_init: { + \bool_set_false:N \l_@@_angle_degree_space_bool + \bool_set_false:N \l_@@_angle_minute_space_bool + \prop_clear:N \l_@@_angle_degree_prop + \prop_clear:N \l_@@_angle_minute_prop + \prop_clear:N \l_@@_angle_second_prop + \tl_clear:N \l_@@_preunit_tl + \tl_set_eq:NN \l_@@_number_unit_product_tl + \l_@@_angle_unit_product_tl + \cs_set_eq:NN \@@_number_in_parse_more:N + \@@_number_in_parse_restricted:N +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\@@_angle_direct:nnn} +%\begin{macro}{ +% \@@_angle_direct_aux_i:nnn , +% \@@_angle_direct_aux_ii:nnn , +% \@@_angle_direct_aux_iii:nnn +%} +% When printing an arc directly, there is still the need to fill in +% any zero values required and to check the spacing is correct. That +% is done using a chain approach, which is easy to implement and +% reasonably clear. +% \begin{macrocode} +\cs_new_protected:Npn \@@_angle_direct:nnn #1 { + \tl_if_empty:nTF {#1} + { + \bool_if:NTF \l_@@_angle_degree_zero_bool + { \@@_angle_direct_aux_i:nnn { 0 } } + { \@@_angle_direct_aux_i:nnn { } } + } + { \@@_angle_direct_aux_i:nnn {#1} } +} +\cs_new_protected:Npn \@@_angle_direct_aux_i:nnn #1#2 { + \tl_if_empty:nTF {#2} + { + \bool_if:NTF \l_@@_angle_minute_zero_bool + { \@@_angle_direct_aux_ii:nnn {#1} { 0 } } + { \@@_angle_direct_aux_ii:nnn {#1} { } } + } + { \@@_angle_direct_aux_ii:nnn {#1} {#2} } +} +\cs_new_protected:Npn \@@_angle_direct_aux_ii:nnn #1#2#3 { + \tl_if_empty:nTF {#3} + { + \bool_if:NTF \l_@@_angle_second_zero_bool + { \@@_angle_direct_aux_iii:nnn {#1} {#2} { 0 } } + { \@@_angle_direct_aux_iii:nnn {#1} {#2} { } } + } + { \@@_angle_direct_aux_iii:nnn {#1} {#2} {#3} } +} +\cs_new_protected:Npn \@@_angle_direct_aux_iii:nnn #1#2#3 { + \tl_if_empty:nF {#1} + { + \tl_if_empty:nF {#2#3} + { \bool_set_true:N \l_@@_angle_degree_space_bool } + } + \tl_if_empty:nF {#2} + { + \tl_if_empty:nF {#3} + { \bool_set_true:N \l_@@_angle_minute_space_bool } + } + \@@_angle_print_direct:nnn {#1} {#2} {#3} +} +% \end{macrocode} +%\end{macro} +%\end{macro} +% +%\begin{macro}{ +% \@@_angle_parse:nnn , +% \@@_angle_check_sign: , +% \@@_angle_zero_fill: , +% \@@_angle_sign_shuffle:nn +%} +%\begin{macro}{ +% \@@_angle_parse_aux:nnn , +% \@@_angle_check_sign:n , +% \@@_angle_sign_shuffle_aux:nnn +%} +% Parsing an arc requires a number of stages. First, there is the +% basic conversion of the input numbers into three property lists, +% which will contain the data required. There is then a zero-filling +% step, done here so that signs can be shuffled into the correct places. +% After that, a check to make sure there is only one sign for an arc +% before setting up the inter-part spacing and actually printing. +% \begin{macrocode} +\cs_new_protected:Npn \@@_angle_parse:nnn #1#2#3 { + \@@_angle_parse_aux:nn {#1} { degree } + \@@_angle_parse_aux:nn {#2} { minute } + \@@_angle_parse_aux:nn {#3} { second } + \@@_angle_check_sign: + \@@_angle_zero_fill: + \prop_if_empty:NF \l_@@_angle_degree_prop + { + \prop_if_empty:NF \l_@@_angle_minute_prop + { \bool_set_true:N \l_@@_angle_degree_space_bool } + \prop_if_empty:NF \l_@@_angle_second_prop + { \bool_set_true:N \l_@@_angle_degree_space_bool } + } + \prop_if_empty:NF \l_@@_angle_minute_prop + { + \prop_if_empty:NF \l_@@_angle_second_prop + { \bool_set_true:N \l_@@_angle_minute_space_bool } + } + \@@_angle_print: +} +\cs_new_protected:Npn \@@_angle_parse_aux:nn #1#2 { + \prop_clear:N \l_@@_number_in_prop + \tl_if_empty:nF {#1} + { + \@@_number_in_init: + \@@_number_in_parse_aux:n {#1} + } + \prop_get:NnNT \l_@@_number_in_prop { mantissa-sign-deleted } + \l_@@_tmpa_tl + { + \prop_put:NnV \l_@@_number_in_prop { mantissa-sign } + \l_@@_tmpa_tl + } + \@@_number_process: + \prop_set_eq:cN { l_@@_angle_ #2 _prop } + \l_@@_number_in_prop +} +% \end{macrocode} +% Only the highest-order part of an arc can have a sign. This is checked +% now so that the shuffling code is easier to write. +% \begin{macrocode} +\cs_new_protected:Npn \@@_angle_check_sign: { + \prop_if_empty:NTF \l_@@_angle_degree_prop + { + \prop_if_empty:NF \l_@@_angle_minute_prop + { \@@_angle_check_sign_aux:n { second } } + } + { + \@@_angle_check_sign_aux:n { minute } + \@@_angle_check_sign_aux:n { second } + } +} +\cs_new_protected:Npn \@@_angle_check_sign_aux:n #1 { + \prop_if_in:cnTF { l_@@_angle_ #1 _prop } + { mantissa-sign } + { \msg_error:nn { siunitx } { bad-arc-sign } } + { + \prop_if_in:cnT { l_@@_angle_ #1 _prop } + { mantissa-sign-deleted } + { \msg_error:nn { siunitx } { bad-arc-sign } } + } +} +% \end{macrocode} +% Filling in the zero values is rather awkward as there are signs +% to worry about. There is therefore a shuffle to move them into the +% correct places. +% \begin{macrocode} +\cs_new_protected:Npn \@@_angle_zero_fill: { + \bool_lazy_and:nnT + { \l_@@_angle_second_zero_bool } + { \prop_if_empty_p:N \l_@@_angle_second_prop } + { + \prop_put:Nnn \l_@@_angle_second_prop { mantissa } + { true } + \prop_put:Nnn \l_@@_angle_second_prop { mantissa-integer } + { 0 } + } + \bool_lazy_and:nnT + { \l_@@_angle_minute_zero_bool } + { \prop_if_empty_p:N \l_@@_angle_minute_prop } + { + \prop_put:Nnn \l_@@_angle_minute_prop { mantissa } + { true } + \prop_put:Nnn \l_@@_angle_minute_prop { mantissa-integer } + { 0 } + \@@_angle_sign_shuffle:nn { second } { minute } + } + \bool_lazy_and:nnT + { \l_@@_angle_degree_zero_bool } + { \prop_if_empty_p:N \l_@@_angle_degree_prop } + { + \prop_put:Nnn \l_@@_angle_degree_prop { mantissa } + { true } + \prop_put:Nnn \l_@@_angle_degree_prop { mantissa-integer } + { 0 } + \@@_angle_sign_shuffle:nn { second } { degree } + \@@_angle_sign_shuffle:nn { minute } { degree } + } +} +\cs_new_protected:Npn \@@_angle_sign_shuffle:nn #1#2 { + \@@_angle_sign_shuffle_aux:nnn {#1} {#2} { } + \@@_angle_sign_shuffle_aux:nnn {#1} {#2} { -deleted } +} +\cs_new_protected:Npn \@@_angle_sign_shuffle_aux:nnn + #1#2#3 { + \prop_get:cnN { l_@@_angle_ #1 _prop } { mantissa-sign #3 } + \l_@@_tmpa_tl + \prop_remove:cn { l_@@_angle_ #1 _prop } { mantissa-sign #3 } + \quark_if_no_value:NF \l_@@_tmpa_tl + { + \prop_put:cnV { l_@@_angle_ #2 _prop } { mantissa-sign #3 } + \l_@@_tmpa_tl + } +} +% \end{macrocode} +%\end{macro} +%\end{macro} +% +%\begin{macro}{\@@_angle_print:} +%\begin{macro}{\@@_angle_print:nn} +% The standard printing routine examines each part of the arc in turn +% and either does a standard format or calls the special astronomy-style +% routine. There may also be some spaces to add. +% \begin{macrocode} +\cs_new_protected:Npn \@@_angle_print: { + \@@_angle_print_aux:nn { degree } { \SIUnitSymbolDegree } + \bool_if:NT \l_@@_angle_degree_space_bool + { + \nobreak + \l_@@_angle_arc_separator_tl + } + \@@_angle_print_aux:nn { minute } { \SIUnitSymbolArcminute } + \bool_if:NT \l_@@_angle_minute_space_bool + { + \nobreak + \l_@@_angle_arc_separator_tl + } + \@@_angle_print_aux:nn { second } { \SIUnitSymbolArcsecond } +} +\cs_new_protected:Npn \@@_angle_print_aux:nn #1#2 { + \prop_if_empty:cF { l_@@_angle_ #1 _prop } + { + \prop_set_eq:Nc \l_@@_number_in_prop + { l_@@_angle_ #1 _prop } + \tl_set:Nn \l_@@_unit_tl {#2} + \tl_clear:N \l_@@_number_out_tl + \@@_number_format: + \@@_number_output_color: + \bool_if:NTF \l_@@_angle_astronomy_bool + { \@@_angle_print_astronomy: } + { \@@_number_output_single: } + } +} +% \end{macrocode} +%\end{macro} +%\end{macro} +% +%\begin{macro}{\@@_angle_print_astronomy:} +%\begin{macro}{ +% \@@_angle_print_astronomy_aux: , +% \@@_angle_print_astronomy_aux:n , +% \@@_angle_print_astronomy_marker: , +% \@@_angle_print_astronomy_unit: +%} +% The first check for astronomy-style angles is that there is a decimal +% marker in the current input: if not, the standard method can be used. +% The method for the astronomy-style angle is not straight-forward, so +% needs a little explanation. The integer and decimal parts of the +% number are printed at each end of the function. In the middle is a +% method to centre the unit symbol on the decimal marker. This is done +% by typesetting the two symbols and measuring their respective widths. +% The two are then put into zero-width boxes, which allows them to be +% aligned horizontally centred with no vertical change. The larger +% dimension is then used to reconstruct the appropriate width for the +% final output. There is also a need to allow for the \cs{scriptspace} +% added in after superscripts, which otherwise messes up the +% calculation. +% \begin{macrocode} +\cs_new_protected:Npn \@@_angle_print_astronomy: { + \prop_if_in:NnTF \l_@@_number_in_prop + { mantissa-decimal-marker } + { \@@_angle_print_astronomy_aux: } + { \@@_number_output_single: } +} +\cs_new_protected:Npn \@@_angle_print_astronomy_aux: { + \prop_get: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}{\@@_angle_print_direct_aux:nn} +% The direct printing routine is rather similar to the standard +% one, with just a modified final step. +% \begin{macrocode} +\cs_new_protected:Npn \@@_angle_print_direct:nnn #1#2#3 { + \@@_angle_print_direct_aux:nn {#1} { \SIUnitSymbolDegree } + \bool_if:NT \l_@@_angle_degree_space_bool + { + \nobreak + \l_@@_angle_arc_separator_tl + } + \@@_angle_print_direct_aux:nn {#2} { \SIUnitSymbolArcminute } + \bool_if:NT \l_@@_angle_minute_space_bool + { + \nobreak + \l_@@_angle_arc_separator_tl + } + \@@_angle_print_direct_aux:nn {#3} { \SIUnitSymbolArcsecond } +} +\cs_new_protected:Npn \@@_angle_print_direct_aux:nn #1#2 { + \tl_if_empty:nF {#1} + { + \tl_set:Nn \l_@@_unit_tl {#2} + \@@_print:nn { number } { \ensuremath {#1} } + \@@_unit_output_print: + } +} +% \end{macrocode} +%\end{macro} +%\end{macro} +% +%\subsection{Creating unit macros} +% +% Unit macros and related support are created here. To avoid cluttering +% up the user name-space with a lot of short macro names, the standard +% method only makes these available inside the unit-processing functions +% (\cs{SI}, \cs{si} and the \texttt{S} column). +% +%\begin{macro}{\l_siunitx_unit_symbolic_seq} +% A list of all unit and related functions. +% \begin{macrocode} +\seq_new:N \l_siunitx_unit_symbolic_seq +\seq_put_right:Nn \l_siunitx_unit_symbolic_seq { \of } +\seq_put_right:Nn \l_siunitx_unit_symbolic_seq { \highlight } +\seq_put_right:Nn \l_siunitx_unit_symbolic_seq { \per } +\seq_put_right:Nn \l_siunitx_unit_symbolic_seq { \raiseto } +\seq_put_right:Nn \l_siunitx_unit_symbolic_seq { \tothe } +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{ +% \@@_declare_power_after:Nn , +% \@@_declare_power_before:Nn +%} +% Creating powers is all about storing values. +% \begin{macrocode} +\cs_new_protected:Npn \@@_declare_power_after:Nn #1#2 { + \seq_put_right:Nn \l_siunitx_unit_symbolic_seq {#1} + \cs_set:cpn { @@_ \token_to_str:N #1 _literal:w } + { \@@_textsuperscript:n {#2} } + \cs_set:cpn { @@_ \token_to_str:N #1 _function:w } + { \@@_unit_parse_power_after:n {#2} } +} +\cs_new_protected:Npn \@@_declare_power_before:Nn #1#2 { + \seq_put_right:Nn \l_siunitx_unit_symbolic_seq {#1} + \cs_set:cpn { @@_ \token_to_str:N #1 _literal:w } ##1 + { ##1 \@@_textsuperscript:n {#2} } + \cs_set:cpn { @@_ \token_to_str:N #1 _function:w } + { \@@_unit_parse_power_before:n {#2} } +} +% \end{macrocode} +%\end{macro} +% +% \begin{macro}{\@@_declare_prefix:Nnnn} +% \begin{variable} +% {\l_@@_prefix_forward_prop, \l_@@_prefix_reverse_prop} +% Prefixes need to store both the symbol and the power they represent. +% A reverse system is also set up, to allow powers to be converted to +% prefixes. +% \begin{macrocode} +\cs_new_protected:Npn \@@_declare_prefix:Nnnn #1#2#3#4 + { + \seq_put_right:Nn \l_siunitx_unit_symbolic_seq {#1} + \prop_put:Nnn \l_@@_prefix_forward_prop {#1} {#4} + \prop_put:Nnn \l_@@_prefix_reverse_prop {#4} {#1} + \cs_set:cpn { @@_ \token_to_str:N #1 _literal:w } {#2} + \cs_set:cpn { @@_ \token_to_str:N #1 _function:w } + { + \bool_if:NTF \l_@@_prefix_symbols_bool + { \@@_unit_parse_prefix:Nn #1 {#2} } + { \@@_unit_parse_prefix:nn {#3} {#4} } + } + } +\prop_new:N \l_@@_prefix_forward_prop +\prop_new:N \l_@@_prefix_reverse_prop +% \end{macrocode} +% \end{variable} +% \end{macro} +% +%\begin{macro}{\@@_declare_qualifier:Nn} +% Qualifiers just need storing. +% \begin{macrocode} +\cs_new_protected:Npn \@@_declare_qualifier:Nn #1#2 { + \seq_put_right:Nn \l_siunitx_unit_symbolic_seq {#1} + \cs_set:cpn { @@_ \token_to_str:N #1 _literal:w } + { \text { ~ } ( #2 ) } + \cs_set:cpn { @@_ \token_to_str:N #1 _function:w } + { \@@_unit_parse_qualifier:n {#2} } +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\@@_declare_unit:Nnn} +%\begin{macro}{\@@_unit_first_token:n} +% Creating units requires various things to be stored. This is done +% with several storage bins to keep the code clear. For the +% \texttt{macro} definition, the test occurs at use so that there is no +% problem with the creation order for units. +% \begin{macrocode} +\cs_new_protected:Npn \@@_declare_unit:Nnn #1#2#3 { + \seq_put_right:Nn \l_siunitx_unit_symbolic_seq {#1} + \cs_set:cpn { @@_ \token_to_str:N #1 _literal:w } {#2} + \cs_set_protected:cpn { @@_ \token_to_str:N #1 _function:w } + { + \@@_unit_if_literal:nTF {#2} + { \@@_unit_parse_unit:Nn #1 {#2} } + {#2} + } + \tl_if_empty:nTF {#3} + { \cs_undefine:c { l_@@_ \token_to_str:N #1 _options_tl } } + { + \tl_clear_new:c { l_@@_ \token_to_str:N #1 _options_tl } + \tl_set:cn { l_@@_ \token_to_str:N #1 _options_tl } {#3} + } +} +\cs_new_protected:Npn \@@_unit_first_token:n #1 { + \exp_last_unbraced:No \token_to_str:N { \tl_head:w #1 \q_stop } +} +% \end{macrocode} +%\end{macro} +%\end{macro} +% +%\begin{macro}{\per} +% The \cs{per} function is pretty simple. +% \begin{macrocode} +\cs_new:cpn { @@_ \token_to_str:N \per _literal:w } { / } +\cs_new_protected:cpn { @@_ \token_to_str:N \per _function:w } { + \bool_set_true:N \l_@@_per_bool + \@@_unit_parse_per: +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{ +% \raiseto , +% \tothe +%} +% Generic versions of the pre-set powers. +% \begin{macrocode} +\cs_new:cpn { @@_ \token_to_str:N \raiseto _literal:w } #1#2 { + #2 + \@@_textsuperscript:n {#1} +} +\cs_new_protected:cpn { @@_ \token_to_str:N \raiseto _function:w } + #1 { + \@@_unit_parse_power_before:n {#1} +} +\cs_new:cpn { @@_ \token_to_str:N \tothe _literal:w } #1 { + \@@_textsuperscript:n {#1} +} +\cs_new_protected:cpn { @@_ \token_to_str:N \tothe _function:w } + #1 { + \@@_unit_parse_power_after:n {#1} +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\of} +% A flexible qualifier as well. +% \begin{macrocode} +\cs_new:cpn { @@_ \token_to_str:N \of _literal:w } #1 { + \text { ~ } ( #1 ) +} +\cs_new_protected:cpn { @@_ \token_to_str:N \of _function:w } #1 { + \@@_unit_parse_qualifier:n {#1} +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\cancel} +%\begin{macro}{\@@_real_cancel:n} +%\begin{macro}{\@@_cancel:n} +% The \cs{cancel} macro is odd as it is only defined if the appropriate +% package is loaded. +% \begin{macrocode} +\AtBeginDocument { + \cs_if_exist:NT \cancel + { + \cs_set_protected:Npn \@@_cancel:n #1 + { \@@__real_cancel:n { \@@_print:nn { unit } {#1} } } + \cs_set_eq:NN \@@__real_cancel:n \cancel + \seq_put_right:Nn \l_siunitx_unit_symbolic_seq { \cancel } + \cs_new_protected:cpn + { @@_ \token_to_str:N \cancel _function:w } + { \@@_unit_parse_special:n { \@@_cancel:n } } + } +} +% \end{macrocode} +%\end{macro} +%\end{macro} +%\end{macro} +% +%\begin{macro}{\highlight} +% Another special function: selective colour. +% \begin{macrocode} +\cs_new:cpn + { @@_ \token_to_str:N \highlight _literal:w } #1 + { \@@_textcolor:n {#1} } +\cs_new_protected:cpn + { @@_ \token_to_str:N \highlight _function:w } #1 + { \@@_unit_parse_special:n { \@@_textcolor:n {#1} } } +% \end{macrocode} +%\end{macro} +% +%\subsection{Creating body unit macros} +% +% The user might have asked for the unit macros to be available in the +% document body. If so, then these are created at the start of the +% document body. +% +%\begin{macro}{ +% \l_@@_create_free_bool , +% \l_@@_create_overwrite_bool , +% \l_@@_create_prespace_bool , +% \l_@@_create_optional_bool , +% \l_@@_create_xspace_bool +%} +% There are a few options which control this behaviour: these are all +% preamble-only. +% \begin{macrocode} +\keys_define:nn { siunitx } { + free-standing-units .bool_set:N = \l_@@_create_free_bool , + overwrite-functions .bool_set:N = \l_@@_create_overwrite_bool, + space-before-unit .bool_set:N = \l_@@_create_prespace_bool , + unit-optional-argument .bool_set:N = \l_@@_create_optional_bool , + use-xspace .bool_set:N = \l_@@_create_xspace_bool , +} +\@@_option_deactivate:n { + free-standing-units , + overwrite-functions , + space-before-unit , + unit-optional-argument , + use-xspace , +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\@@_unit_create_empty_functions:} +%\begin{macro}{\@@_unit_create_empty_functions_aux:N} +% Without this, horrible things happen with \pkg{memoir} and +% \pkg{hyperref}. +% \begin{macrocode} +\cs_new_protected:Npn \@@_unit_create_empty_functions: + { + \@@_unit_create_functions_aux_i: + \seq_map_function:NN \l_siunitx_unit_symbolic_seq + \@@_unit_create_empty_functions_aux:N + \@@_unit_create_functions_aux_ii: + } +\cs_new_protected:Npn \@@_unit_create_empty_functions_aux:N #1 + { + \cs_if_free:NT #1 + { \cs_set_protected:Npn #1 { \ERROR } } + } +% \end{macrocode} +%\end{macro} +%\end{macro} +% +% \begin{macro}{\@@_unit_create_functions:} +% \begin{macro} +% { +% \@@_unit_create_functions_aux_i:, +% \@@_unit_create_functions_aux_ii: +% } +% Creation of macros essentially involves picking up a couple of loops. +% \begin{macrocode} +\cs_new_protected:Npn \@@_unit_create_functions: + { + \@@_unit_create_functions_aux_i: + \bool_if:NT \l_@@_create_overwrite_bool + { \seq_map_function:NN \l_siunitx_unit_symbolic_seq \cs_undefine:N } + \bool_if:NTF \l_@@_create_optional_bool + { + \seq_map_function:NN \l_siunitx_unit_symbolic_seq + \@@_unit_create_with_arg:N + } + { + \seq_map_function:NN \l_siunitx_unit_symbolic_seq + \@@_unit_create:N + } + \@@_unit_create_functions_aux_ii: + \bool_if:NT \l_@@_create_xspace_bool + { \RequirePackage { xspace } } + } +\cs_new_protected:Npn \@@_unit_create_functions_aux_i: + { + \@ifpackageloaded { soulpos } + { + \@ifpackageloaded { soul } + { } + { + \cs_set_protected:Npn \@@_unit_create_functions_aux_ii: + { + \cs_undefine:N \hl + \cs_undefine:N \ul + } + } + } + { } + } +\cs_new_protected:Npn \@@_unit_create_functions_aux_ii: { } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +%\begin{macro}{ +% \@@_unit_create:N , +% \@@_unit_create_with_arg:N +%} +% The creation functions expand everything as far as possible so that +% there is less to do in the document. +% \begin{macrocode} +\cs_new_protected:Npn \@@_unit_create:N #1 { + \cs_if_free:NT #1 + { + \cs_set:Npx \@@_tmp:w + { + \ProvideDocumentCommand \exp_not:N #1 { } + { + \group_begin: + \exp_not:N \cs_if_free:NF + \exp_not:c + { l_@@_ \token_to_str:N #1 _options_tl } + { + \keys_set:nV { siunitx } + \exp_not:c + { l_@@_ \token_to_str:N #1 _options_tl } + } + \bool_if:NT \l_@@_create_prespace_bool + { \exp_not:N \l_@@_number_unit_product_tl } + \exp_not:n { \@@_unit_output:nn {#1} { } } + \group_end: + \bool_if:NT \l_@@_create_xspace_bool + { \exp_not:N \xspace } + } + } + \@@_tmp:w + } +} +\cs_new_protected:Npn \@@_unit_create_with_arg:N #1 { + \cs_if_free:NT #1 + { + \cs_set:Npx \@@_tmp:w + { + \ProvideDocumentCommand \exp_not:N #1 { o } + { + \group_begin: + \exp_not:N \cs_if_free:NF + \exp_not:c + { l_@@_ \token_to_str:N #1 _options_tl } + { + \keys_set:nV { siunitx } + \exp_not:c + { + l_@@_ \token_to_str:N #1 _options_tl + } + } + \exp_not:N \IfNoValueTF {####1} + { + \bool_if:NT \l_@@_create_prespace_bool + { \exp_not:N \l_@@_number_unit_product_tl } + \exp_not:n { \@@_unit_output:nn {#1} { } } + } + { \SI {####1} { \exp_not:N #1 } } + \group_end: + \bool_if:NT \l_@@_create_xspace_bool + { \exp_not:N \xspace } + } + } + \@@_tmp:w + } +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\@@_protect_symbols:N} +% There are a few unit names which may be defined by other parts of +% \LaTeX. They need to be unexpandable, as in an \texttt{S} column +% \TeX{} will look for \cs{omit} \emph{before} starting the internal +% version of \cs{si} and doing a redefinition. The same is true +% for the \cs{color} function, which may well be the first thing in +% a table cell. The same is true for \cs{array@row@rst}, from REV\TeX, +% which otherwise gives an error. +% \begin{macrocode} +\AtBeginDocument { + \cs_if_eq:NNT \color \use_none:n + { \cs_set_protected:Npn \color #1 { } } + \cs_set:Npn \@@_tmp:w #1 { } + \cs_if_eq:NNT \color \@@_tmp:w + { \cs_set_protected:Npn \color #1 { } } + \tl_map_function:nN { \bar \color \ng \pm \array@row@rst } + \@@_protect_symbols:N +} +\tl_put_right:Nn \document { \@@_protect_symbols:N \fg } +\cs_new_protected:Npn \@@_protect_symbols:N #1 { + \cs_if_exist:NT #1 + { + \tl_if_empty:fT { \token_get_prefix_spec:N #1 } + { \cs_set_protected:Npx #1 { \exp_not:V #1 } } + } +} +% \end{macrocode} +%\end{macro} +% +%\subsection{Initial unit processing} +% +% The unit processor has to convert the input (which may be all macros +% or may contain literal input) into formatted text for output. The +% input part of the process is used to sort out parsed or literal units. +% +%\begin{macro}{ +% \l_@@_unit_forbid_literal_bool , +% \l_@@_unit_parse_bool +%} +% One option is related to how units are pre-processed. +% \begin{macrocode} +\keys_define:nn { siunitx } { + forbid-literal-units .bool_set:N = + \l_@@_unit_forbid_literal_bool, + parse-units .bool_set:N = \l_@@_unit_parse_bool +} +\keys_set:nn { siunitx } { + forbid-literal-units = false, + parse-units = true +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{ +% \@@_unit_in:nn , +% \@@_unit_in:Vn , +% \@@_pm: +%} +% The master function does a very simple checks then hands off. +% The definition of \cs{pm} needs to be saved here so that it can +% safely be used as an abbreviation for picometre and also in numbers +% for \( \pm \). +% \begin{macrocode} +\cs_new_protected:Npn \@@_unit_in:nn #1#2 { + \bool_if:NTF \l_@@_unit_parse_bool + { + \tl_if_empty:nF {#1} + { + \@@_unit_if_literal:nTF {#1} + { + \tl_clear:N \l_@@_per_mode_tl + \bool_if:NTF \l_@@_unit_forbid_literal_bool + { + \msg_error:nnx { siunitx } { literal-unit } + { \exp_not:n {#1} } + } + { + \cs_set_eq:NN \@@_pm: \pm + \@@_unit_format_literal:n {#1} + \cs_set_eq:NN \pm \@@_pm: + } + } + { + \cs_set_eq:NN \@@_pm: \pm + \@@_unit_parse:nn {#1} {#2} + \@@_unit_format: + \prop_set_eq:NN \l_@@_unit_saved_prop \l_@@_unit_prop + \cs_set_eq:NN \pm \@@_pm: + } + } + } + { \@@_unit_format_literal:n {#1} } +} +\cs_generate_variant:Nn \@@_unit_in:nn { V } +\cs_new:Npn \@@_pm: { } +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\@@_unit_if_literal:nTF} +%\begin{macro}{\@@_unit_if_literal_aux:N} +% A test is needed to see if the input only contains unit macros. This +% is done by altering setting all of the unit macros to expand to +% nothing at all. Thus there will only be anything left if there is +% a literal in the unit. +% \begin{macrocode} +\cs_new_protected:Npn \@@_unit_if_literal:nTF #1#2#3 { + \group_begin: + \seq_map_function:NN \l_siunitx_unit_symbolic_seq + \@@_unit_if_literal_aux:N + \cs_set_eq:NN \of \use_none:n + \cs_set_eq:NN \highlight \use_none:n + \cs_set_eq:NN \raiseto \use_none:n + \cs_set_eq:NN \tothe \use_none:n + \protected@edef \l_@@_tmpa_tl {#1} + \exp_args:NNNV \group_end: + \tl_set:Nn \l_@@_tmpa_tl \l_@@_tmpa_tl + \tl_if_blank:VTF \l_@@_tmpa_tl {#3} {#2} +} +\cs_new_protected:Npn \@@_unit_if_literal_aux:N #1 { + \cs_set_eq:NN #1 \prg_do_nothing: +} +% \end{macrocode} +%\end{macro} +%\end{macro} +% +%\subsection{Parsing macro units} +% +% For macro-based units, the macros are converted into literal text, +% which is then passed on for printing. The code reads through the +% input to collect up the units, before re-combining everything into +% a single block at the end of the process. +% +% \begin{variable} +% { +% \l_@@_unit_int , +% \l_@@_unit_prop , +% \l_@@_unit_saved_prop +% } +% Parsed units are stored in a property list, to keep things compact. +% An integer is also needed to count up units. +% \begin{macrocode} +\int_new:N \l_@@_unit_int +\prop_new:N \l_@@_unit_prop +\prop_new:N \l_@@_unit_saved_prop +% \end{macrocode} +% \end{variable} +% +%\begin{macro}{\l_@@_per_bool} +% To allow \cs{per} to be \enquote{sticky}. +% \begin{macrocode} +\bool_new:N \l_@@_per_bool +% \end{macrocode} +%\end{macro} +% +% \begin{variable} +% { +% \l_@@_exp_to_prefix_bool , +% \l_@@_prefix_symbols_bool , +% \l_@@_sticky_per_bool +% } +% Some options are directly related to how units are handled at this +% stage, so need be created before the reconstruction part of the code. +% \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_siunitx_unit_symbolic_seq + { \cs_set_eq:Nc ##1 { @@_ \token_to_str:N ##1 _function:w } } + } +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\@@_unit_parse_options:n} +% Any unit-specific options are loaded, followed by re-applying any +% options given for this particular macro. The second call to +% \cs{keys_set:nn} is needed to allow the local overriding of settings. +% \begin{macrocode} +\cs_new_protected:Npn \@@_unit_parse_options:nn #1#2 { + \tl_if_single:nT {#1} + { + \cs_if_free:cF + { l_@@_ \@@_unit_first_token:n {#1} _options_tl } + { + \keys_set:nv { siunitx } + { l_@@_ \@@_unit_first_token:n {#1} _options_tl } + \keys_set:nn { siunitx } {#2} + } + } +} +% \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}{\@@_unit_parse_unit_per:} +% For units, there is a check in case a prefix is present (which will +% have incremented the counter). With the counter correct, simply add +% the literal to the property list. There is also a check to see if +% there is a \enquote{sticky} \cs{per} to think about. +% \begin{macrocode} +\cs_new_protected:Npn \@@_unit_parse_unit:Nn #1#2 { + \tl_set:Nx \l_@@_tmpa_tl + { prefix-symbol- \int_use:N \l_@@_unit_int } + \prop_if_in:NVTF \l_@@_unit_prop \l_@@_tmpa_tl + { + \tl_set:Nx \l_@@_tmpa_tl + { symbol- \int_use:N \l_@@_unit_int } + \prop_if_in:NVT \l_@@_unit_prop \l_@@_tmpa_tl + { \int_incr:N \l_@@_unit_int } + } + { \int_incr:N \l_@@_unit_int } + \tl_set:Nx \l_@@_tmpa_tl + { unit- \int_use:N \l_@@_unit_int } + \prop_put:NVn \l_@@_unit_prop \l_@@_tmpa_tl {#1} + \tl_set:Nx \l_@@_tmpa_tl + { symbol- \int_use:N \l_@@_unit_int } + \prop_put:NVn \l_@@_unit_prop \l_@@_tmpa_tl {#2} + \@@_unit_parse_unit_per: +} +\cs_new_protected:Npn \@@_unit_parse_unit_per: { + \bool_if:NT \l_@@_sticky_per_bool + { + \bool_if:NT \l_@@_per_bool + { + \tl_set:Nx \l_@@_tmpa_tl + { per- \int_use:N \l_@@_unit_int } + \prop_put:NVn \l_@@_unit_prop \l_@@_tmpa_tl + { true } + } + } +} +% \end{macrocode} +%\end{macro} +%\end{macro} +% +%\subsection{Unit formatting} +% +%\begin{macro}{ +% \l_@@_preunit_tl , +% \l_@@_unit_tl , +% \l_@@_unit_current_tl , +% \l_@@_unit_denominator_tl , +% \l_@@_unit_numerator_tl , +% \l_@@_unit_saved_tl +%} +% Storage space for creating unit output. +% \begin{macrocode} +\tl_new:N \l_@@_preunit_tl +\tl_new:N \l_@@_unit_tl +\tl_new:N \l_@@_unit_current_tl +\tl_new:N \l_@@_unit_denominator_tl +\tl_new:N \l_@@_unit_numerator_tl +\tl_new:N \l_@@_unit_saved_tl +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{ +% \l_@@_unit_denominator_int , +% \l_@@_unit_numerator_int +%} +% For tracking in case brackets are needed. +% \begin{macrocode} +\int_new:N \l_@@_unit_denominator_int +\int_new:N \l_@@_unit_numerator_int +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{ +% \l_@@_unit_prefix_int , +% \l_@@_unit_prefix_base_int , +% \l_@@_unit_prefix_current_tl +%} +% Used to calculate the overall prefix value. +% \begin{macrocode} +\int_new:N \l_@@_unit_prefix_int +\int_new:N \l_@@_unit_prefix_base_int +\tl_new:N \l_@@_unit_prefix_current_tl +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\l_@@_unit_prefix_gram_int} +% Formatting units is complicated by the fact that the kilogram is a +% base unit, making conversions a little more awkward. +% \begin{macrocode} +\int_new:N \l_@@_unit_prefix_gram_int +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\l_@@_omit_unit_space_bool} +% Needed to omit the space between a number an a unit when printing +% symbols and when there is no numerator unit. +% \begin{macrocode} +\bool_new:N \l_@@_omit_unit_space_bool +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{ +% \l_@@_per_auto_bool , +% \l_@@_per_fraction_bool , +% \l_@@_per_mode_tl , +% \l_@@_power_number_bool , +% \l_@@_qualifier_mode_tl , +% \l_@@_per_two_parts_bool +%} +% For saving settings. +% \begin{macrocode} +\bool_new:N \l_@@_per_auto_bool +\bool_new:N \l_@@_per_fraction_bool +\tl_new:N \l_@@_per_mode_tl +\bool_new:N \l_@@_power_number_bool +\bool_new:N \l_@@_per_two_parts_bool +\tl_new:N \l_@@_qualifier_mode_tl +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{ +% \l_@@_unit_denominator_bracket_bool , +% \l_@@_unit_product_tl , +% \l_@@_literal_power_bool , +% \l_@@_per_symbol_tl , +% \l_@@_qualifier_phrase_tl +%} +% At this stage, output formatting options are created. +% \begin{macrocode} +\keys_define:nn { siunitx } { + bracket-unit-denominator .bool_set:N + = \l_@@_unit_denominator_bracket_bool, + inter-unit-product .tl_set:N = \l_@@_unit_product_tl , + inter-unit-separator .tl_set:N = \l_@@_unit_product_tl , + literal-superscript-as-power + .bool_set:N = \l_@@_literal_power_bool, + per-mode .choice:, + per-mode / fraction .code:n = + { + \bool_set_false:N \l_@@_per_auto_bool + \bool_set_true:N \l_@@_per_fraction_bool + \bool_set_true:N \l_@@_per_two_parts_bool + \tl_set:Nn \l_@@_per_mode_tl { fraction } + }, + per-mode / power .meta:n = { per-mode = reciprocal } , + per-mode / power-positive-first .meta:n = + { per-mode = reciprocal-positive-first } , + per-mode / reciprocal .code:n = + { + \bool_set_false:N \l_@@_per_auto_bool + \bool_set_false:N \l_@@_per_fraction_bool + \bool_set_false:N \l_@@_per_two_parts_bool + \tl_clear:N \l_@@_per_mode_tl + }, + per-mode / reciprocal-positive-first .code:n = + { + \bool_set_false:N \l_@@_per_auto_bool + \bool_set_false:N \l_@@_per_fraction_bool + \bool_set_true:N \l_@@_per_two_parts_bool + \tl_clear:N \l_@@_per_mode_tl + }, + per-mode / repeated-symbol .code:n = + { + \bool_set_false:N \l_@@_per_auto_bool + \bool_set_false:N \l_@@_per_fraction_bool + \bool_set_false:N \l_@@_per_two_parts_bool + \tl_set:Nn \l_@@_per_mode_tl { repeat } + }, + per-mode / symbol .code:n = + { + \bool_set_false:N \l_@@_per_auto_bool + \bool_set_true:N \l_@@_per_fraction_bool + \bool_set_true:N \l_@@_per_two_parts_bool + \tl_set:Nn \l_@@_per_mode_tl { symbol } + }, + per-mode / symbol-or-fraction .code:n = + { + \bool_set_true:N \l_@@_per_auto_bool + \bool_set_true:N \l_@@_per_fraction_bool + \bool_set_true:N \l_@@_per_two_parts_bool + \tl_set:Nn \l_@@_per_mode_tl { symbol } + }, + per-symbol .tl_set:N = \l_@@_per_symbol_tl, + power-font .choice:, + power-font / number .code:n = + { \bool_set_true:N \l_@@_power_number_bool }, + power-font / unit .code:n = + { \bool_set_false:N \l_@@_power_number_bool }, + qualifier-mode .choice:, + qualifier-mode / brackets .code:n = + { \tl_set:Nn \l_@@_qualifier_mode_tl { brackets } }, + qualifier-mode / phrase .code:n = + { \tl_set:Nn \l_@@_qualifier_mode_tl { phrase } }, + qualifier-mode / space .code:n = + { \tl_set:Nn \l_@@_qualifier_mode_tl { space } }, + qualifier-mode / subscript .code:n = + { \tl_set:Nn \l_@@_qualifier_mode_tl { subscript } }, + qualifier-mode / text .code:n = + { \tl_set:Nn \l_@@_qualifier_mode_tl { text } }, + qualifier-phrase .tl_set:N = \l_@@_qualifier_phrase_tl +} +\keys_set:nn { siunitx } { + bracket-unit-denominator = true, + inter-unit-product = \,, + literal-superscript-as-power = true, + per-mode = reciprocal, + per-symbol = /, + power-font = number, + qualifier-mode = subscript, + qualifier-phrase = { ~ of ~ } +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\@@_unit_format:} +% Most of the work is done by the loop, with a little tidying up for +% fraction-like output. Before starting the loop, there is a check for +% the case of a single reciprocal unit when per is set up to create a +% symbol. In that special case, the space between a number and a unit +% has to be removed. +% \begin{macrocode} +\cs_new_protected:Npn \@@_unit_format: { + \prop_put:Nnx \l_@@_unit_prop { total-units } + { \int_use:N \l_@@_unit_int } + \@@_unit_format_init: + \int_while_do:nNnn { \l_@@_unit_int } > { 0 } + { + \@@_unit_format_prefix: + \@@_unit_format_symbol: + \@@_unit_format_qualifier: + \@@_unit_format_power: + \@@_unit_format_add: + \int_decr:N \l_@@_unit_int + } + \bool_if:NT \l_@@_per_two_parts_bool + { + \bool_if:NTF \l_@@_per_fraction_bool + { \@@_unit_format_fraction: } + { \@@_unit_format_sorted: } + } +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\@@_unit_format_add:} +%\begin{macro}{\@@_unit_format_add_aux:n} +% Adding the current unit to the output means checking where it goes. +% The odd code when adding a space is to pick up repeated per symbols, +% which need to suppress the space. +% \begin{macrocode} +\cs_new_protected:Npn \@@_unit_format_add: { + \bool_if:NTF \l_@@_per_two_parts_bool + { + \tl_set:Nx \l_@@_tmpb_tl + { per- \int_use:N \l_@@_unit_int } + \prop_if_in:NVTF \l_@@_unit_prop \l_@@_tmpb_tl + { + \@@_unit_format_add_aux:n { _denominator } + \int_incr:N \l_@@_unit_denominator_int + } + { + \@@_unit_format_add_aux:n { _numerator } + \int_incr:N \l_@@_unit_numerator_int + } + } + { \@@_unit_format_add_aux:n { } } + \tl_clear:N \l_@@_unit_current_tl +} +\cs_new_protected:Npn \@@_unit_format_add_aux:n #1 { + \tl_if_empty:cF { l_@@_unit #1 _tl } + { + \str_if_eq:VnTF \l_@@_per_mode_tl { repeat } + { + \tl_set:Nx \l_@@_tmpa_tl + { per- \int_eval:n { \l_@@_unit_int + 1 } } + \prop_if_in:NVF \l_@@_unit_prop \l_@@_tmpa_tl + { + \tl_put_right:NV \l_@@_unit_current_tl + \l_@@_unit_product_tl + } + } + { + \tl_put_right:NV \l_@@_unit_current_tl + \l_@@_unit_product_tl + } + } + \tl_set:Nx \l_@@_tmpa_tl + { special- \int_use:N \l_@@_unit_int } + \prop_get:NVNTF \l_@@_unit_prop \l_@@_tmpa_tl + \l_@@_tmpa_tl + { + \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}{ +% \@@_unit_format_fraction: , +% \@@_unit_format_auto: , +% \@@_unit_format_symbol: , +% \@@_unit_format_symbol_aux: , +% \@@_unit_format_symbol_aux_alt: +%} +% When making (\emph{psuedo}-)fractions there is a check to place a +% \( 1 \) in the numerator is it's blank. For symbol mode, this is +% only done if there is no number. Then some construction work. +% \begin{macrocode} +\cs_new_protected:Npn \@@_unit_format_fraction: { + \int_compare:nNnT { \l_@@_unit_numerator_int } = { 0 } + { + \str_if_eq:VnT \l_@@_per_mode_tl { symbol } + { \bool_set_true:N \l_@@_omit_unit_space_bool } + } + \int_compare:nNnTF { \l_@@_unit_denominator_int } > { 0 } + { + \bool_if:NTF \l_@@_per_auto_bool + { \@@_unit_format_fraction_auto: } + { + \use:c + { @@_unit_format_fraction_ \l_@@_per_mode_tl : } + } + } + { \tl_set_eq:NN \l_@@_unit_tl \l_@@_unit_numerator_tl } +} +\cs_new_protected:Npn \@@_unit_format_fraction_fraction: { + \tl_if_empty:NT \l_@@_unit_numerator_tl + { \tl_set:Nn \l_@@_unit_numerator_tl { 1 } } + \tl_set:Nx \l_@@_unit_numerator_tl + { { \exp_not:V \l_@@_unit_numerator_tl } } + \tl_put_left:Nn \l_@@_unit_numerator_tl + { \@@_print:nn { unit } } + \tl_set:Nx \l_@@_unit_numerator_tl + { { \exp_not:V \l_@@_unit_numerator_tl } } + \tl_set:Nx \l_@@_unit_denominator_tl + { { \exp_not:V \l_@@_unit_denominator_tl } } + \tl_put_left:Nn \l_@@_unit_denominator_tl + { \@@_print:nn { unit } } + \tl_set:Nx \l_@@_unit_denominator_tl + { { \exp_not:V \l_@@_unit_denominator_tl } } + \tl_set:Nn \l_@@_unit_tl { \@@_fraction:nn } + \tl_put_right:NV \l_@@_unit_tl \l_@@_unit_numerator_tl + \tl_put_right:NV \l_@@_unit_tl \l_@@_unit_denominator_tl + \tl_set:Nx \l_@@_unit_tl + { \exp_not:N \ensuremath { \exp_not:V \l_@@_unit_tl } } +} +% \end{macrocode} +% For the \opt{symbol} setting, there is a need to deal with the +% possible \opt{symbol-or-fraction} choice. That is achieved by +% setting up both the \opt{fraction} and \opt{symbol} output. +% In the automatic mode, both cases are combined inside a +% \cs{tex_mathchoice:D}, with appropriate protection, before sending +% everything through for printing. +% \begin{macrocode} +\cs_new_protected:Npn \@@_unit_format_fraction_auto: { + \mode_if_math:TF + { + \group_begin: + \@@_unit_format_fraction_fraction: + \exp_args:NNNV \group_end: + \tl_set:Nn \l_@@_tmpa_tl \l_@@_unit_tl + \group_begin: + \@@_unit_format_fraction_symbol: + \exp_args:NNNV \group_end: + \tl_set:Nn \l_@@_tmpb_tl \l_@@_unit_tl + \tl_set:Nx \l_@@_tmpb_tl + { + \@@_print:nn { unit } + { \exp_not:V \l_@@_tmpb_tl } + } + \tl_set:Nx \l_@@_unit_tl + { + \exp_not:N \ensuremath { + \tex_mathchoice:D + { \exp_not:V \l_@@_tmpa_tl } + { \exp_not:V \l_@@_tmpb_tl } + { \exp_not:V \l_@@_tmpb_tl } + { \exp_not:V \l_@@_tmpb_tl } + } + } + } + { \@@_unit_format_fraction_symbol: } +} +% \end{macrocode} +% For a normal symbol, the two parts of the input are arranged either +% side of the symbol itself in math mode. +% \begin{macrocode} +\cs_new_protected:Npn \@@_unit_format_fraction_symbol: { + \@@_unit_format_fraction_symbol_aux: + \int_compare:nNnT { \l_@@_unit_denominator_int } > { 1 } + { + \bool_if:NT \l_@@_unit_denominator_bracket_bool + { + \tl_put_left:NV \l_@@_unit_denominator_tl \l_@@_bracket_open_tl + \tl_put_right:NV \l_@@_unit_denominator_tl \l_@@_bracket_close_tl + } + } + \tl_set_eq:NN \l_@@_unit_tl \l_@@_unit_numerator_tl + \tl_put_right:NV \l_@@_unit_tl \l_@@_per_symbol_tl + \tl_put_right:NV \l_@@_unit_tl \l_@@_unit_denominator_tl +} +\cs_new_protected:Npn + \@@_unit_format_fraction_symbol_aux: { } +\cs_new_protected:Npn + \@@_unit_format_fraction_symbol_aux_alt: { + \tl_if_empty:NT \l_@@_unit_numerator_tl + { \tl_set:Nn \l_@@_unit_numerator_tl { 1 } } +} +% \end{macrocode} +%\end{macro} +%\end{macro} +% +%\begin{macro}{\@@_unit_format_init:} +% The normal initialisation stuff. +% \begin{macrocode} +\cs_new_protected:Npn \@@_unit_format_init: { + \bool_set_false:N \l_@@_omit_unit_space_bool + \tl_clear:N \l_@@_unit_tl + \tl_clear:N \l_@@_unit_current_tl + \tl_clear:N \l_@@_unit_denominator_tl + \int_zero:N \l_@@_unit_prefix_gram_int + \tl_clear:N \l_@@_unit_numerator_tl + \int_zero:N \l_@@_unit_prefix_base_int + \int_zero:N \l_@@_unit_prefix_int + \int_zero:N \l_@@_unit_denominator_int + \int_zero:N \l_@@_unit_numerator_int + \seq_map_inline:Nn \l_siunitx_unit_symbolic_seq + { \@@_unit_print_literal_aux:N ##1 } +} +% \end{macrocode} +%\end{macro} +% +% \begin{macro}{\@@_unit_format_literal:n} +% \begin{macro}{\@@_unit_format_literal_aux:N} +% \begin{macro}{\@@_unit_format_literal_power:n} +% If the unit given contains anything which is not a unit macro, then +% any unit macros that are there simply dump literal meanings. There is +% then a little work to do sorting out |~| and |.| characters at +% the outer level. +% \begin{macrocode} +\group_begin: + \char_set_catcode_active:N \~ + \cs_new_protected:Npn \@@_unit_format_literal:n #1 + { + \int_zero:N \l_@@_unit_prefix_int + \seq_map_inline:Nn \l_siunitx_unit_symbolic_seq + { \@@_unit_print_literal_aux:N ##1 } + \tl_set:Nn \l_@@_unit_tl {#1} + \tl_replace_all:NnV \l_@@_unit_tl { . } + \l_@@_unit_product_tl + \tl_replace_all:NnV \l_@@_unit_tl { ~ } + \l_@@_unit_product_tl + \bool_if:NT \l_@@_literal_power_bool + { + \tl_replace_all:Nnn \l_@@_unit_tl { ^ } + { \@@_unit_format_literal_power:n } + \tl_replace_all:Non \l_@@_unit_tl { \token_to_str:N ^ } + { \@@_unit_format_literal_power:n } + } + \@@_unit_format_literal_extras: + } +\group_end: +\cs_new_protected:Npn \@@_unit_print_literal_aux:N #1 + { \cs_set_eq:Nc #1 { @@_ \token_to_str:N #1 _literal:w } } +\cs_new_protected:Npn \@@_unit_format_literal_power:n #1 + { \PrintSuperscript { \@@_unit_format_power_aux:n {#1} } } +% \end{macrocode} +% \end{macro} +% \end{macro} + %\end{macro} +% +%\begin{macro}{\@@_unit_format_literal_extras:} +%\begin{macro}{\@@_unit_format_literal_extras_aux:nN} +% The code here deals with characters outside the normal range that +% can appear in units in UTF-8 and related encodings. The idea is to +% do a search and replace, thus avoiding any active characters. +% \begin{macrocode} +\cs_new_protected:Npn \@@_unit_format_literal_extras: + { + \@@_unit_format_literal_extras_aux:nN { 176 } + \SIUnitSymbolDegree + \@@_unit_format_literal_extras_aux:nN { 181 } + \SIUnitSymbolMicro + \@@_unit_format_literal_extras_aux:nN { 197 } + \SIUnitSymbolAngstrom + } +\cs_new_protected:Npn \@@_unit_format_literal_extras_aux:nN #1#2 + { + \tl_replace_all:Nxn \l_@@_unit_tl + { \char_generate:nn { #1 } { 12 } } + {#2} + } +\bool_lazy_or:nnF { \sys_if_engine_luatex_p: } { \sys_if_engine_xetex_p: } + { + \AtBeginDocument + { + \cs_if_exist:NTF \inputencodingname + { + \tl_set:Nn \l_@@_tmpa_tl { latin1 , latin5 , latin9 } + \clist_if_in:NVF \l_@@_tmpa_tl \inputencodingname + { + \cs_set_eq:NN \@@_unit_format_literal_extras: + \scan_stop: + } + } + { + \cs_set_eq:NN \@@_unit_format_literal_extras: + \scan_stop: + } + } + } +% \end{macrocode} +%\end{macro} +%\end{macro} +% +%\begin{macro}{\@@_unit_format_power:} +%\begin{macro}{ +% \@@_unit_format_power_aux: , +% \@@_unit_format_power_aux:n , +% \@@_unit_format_power_aux:nn , +% \@@_unit_format_power_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}{ +% \@@_unit_format_prefix_number: , +% \@@_unit_format_prefix_number_calc: , +% \@@_unit_format_prefix_symbol: +%} +% If there is a prefix, it is added to the output. When using numerical +% output, some conversion is needed instead. +% \begin{macrocode} +\cs_new_protected:Npn \@@_unit_format_prefix: { + \tl_set:Nx \l_@@_tmpa_tl + { prefix-symbol- \int_use:N \l_@@_unit_int } + \prop_if_in:NVT \l_@@_unit_prop \l_@@_tmpa_tl + { + \prop_get:NVN \l_@@_unit_prop \l_@@_tmpa_tl + \l_@@_unit_prefix_current_tl + \bool_if:NTF \l_@@_prefix_symbols_bool + { \@@_unit_format_prefix_symbol: } + { \@@_unit_format_prefix_number: } + } +} +\cs_new_protected:Npn \@@_unit_format_prefix_number: { + \tl_set:Nx \l_@@_tmpa_tl + { prefix-base- \int_use:N \l_@@_unit_int } + \prop_get:NVN \l_@@_unit_prop \l_@@_tmpa_tl + \l_@@_tmpa_tl + \int_compare:nNnT { \l_@@_unit_prefix_base_int } = { 0 } + { + \int_set:Nn \l_@@_unit_prefix_base_int + { \l_@@_tmpa_tl } + } + \int_compare:nNnTF + { \l_@@_unit_prefix_base_int } = { \l_@@_tmpa_tl } + { \@@_unit_format_prefix_number_calc: } + { \msg_error:nn { siunitx } { prefix-base-mismatch } } +} +% \end{macrocode} +% The calculation for converting a unit prefix into a number is +% simple unless there are grammes involved. In that case, the base unit +% is the kilogram and so there is some code to convert the number +% back correctly. +% \begin{macrocode} +\cs_new_protected:Npn \@@_unit_format_prefix_number_calc: { + \tl_set:Nx \l_@@_tmpa_tl + { power- \int_use:N \l_@@_unit_int } + \prop_get:NVNF \l_@@_unit_prop \l_@@_tmpa_tl + \l_@@_tmpa_tl + { \tl_set:Nn \l_@@_tmpa_tl { 1 } } + \tl_set:Nx \l_@@_tmpb_tl + { unit- \int_use:N \l_@@_unit_int } + \prop_get:NVN \l_@@_unit_prop \l_@@_tmpb_tl + \l_@@_tmpb_tl + \str_if_eq:VnT \l_@@_tmpb_tl { \gram } + { + \tl_set:Nx \l_@@_unit_prefix_current_tl + { \int_eval:n { \l_@@_unit_prefix_current_tl - 3 } } + \tl_set:Nx \l_@@_tmpb_tl + { symbol- \int_use:N \l_@@_unit_int } + \prop_put:NVn \l_@@_unit_prop \l_@@_tmpb_tl { kg } + } + \tl_set:Nx \l_@@_unit_prefix_current_tl + { + \int_eval:n + { \l_@@_unit_prefix_current_tl * \l_@@_tmpa_tl } + } + \tl_set:Nx \l_@@_tmpa_tl + { per- \int_use:N \l_@@_unit_int } + \prop_if_in:NVTF \l_@@_unit_prop \l_@@_tmpa_tl + { + \int_set:Nn \l_@@_unit_prefix_int + { + \l_@@_unit_prefix_int + - \l_@@_unit_prefix_current_tl + } + } + { + \int_set:Nn \l_@@_unit_prefix_int + { + \l_@@_unit_prefix_int + + \l_@@_unit_prefix_current_tl + } + } +} +\cs_new_protected:Npn \@@_unit_format_prefix_symbol: { + \tl_set_eq:NN \l_@@_unit_current_tl + \l_@@_unit_prefix_current_tl +} +% \end{macrocode} +%\end{macro} +%\end{macro} +% +%\begin{macro}{\@@_unit_format_qualifier:} +%\begin{macro}{ +% \@@_unit_format_qualifier_brackets: , +% \@@_unit_format_qualifier_phrase: , +% \@@_unit_format_qualifier_space: , +% \@@_unit_format_qualifier_subscript: , +% \@@_unit_format_qualifier_text: +%} +% Four methods for showing qualifiers, each with its own sub-function. +% For the \texttt{space} methods, a warning is set in the property list +% as if there is a power then some brackets will be needed. +% \begin{macrocode} +\cs_new_protected:Npn \@@_unit_format_qualifier: { + \tl_set:Nx \l_@@_tmpa_tl + { qualifier- \int_use:N \l_@@_unit_int } + \prop_get:NVNT \l_@@_unit_prop \l_@@_tmpa_tl + \l_@@_tmpa_tl + { + \use:c + { + @@_unit_format_qualifier_ + \l_@@_qualifier_mode_tl : + } + } +} +\cs_new_protected:Npn \@@_unit_format_qualifier_brackets: { + \tl_put_right:NV \l_@@_unit_current_tl \l_@@_bracket_open_tl + \tl_put_right:NV \l_@@_unit_current_tl \l_@@_tmpa_tl + \tl_put_right:NV \l_@@_unit_current_tl \l_@@_bracket_close_tl +} +\cs_new_protected:Npn \@@_unit_format_qualifier_phrase: + { + \tl_put_right:NV \l_@@_unit_current_tl \l_@@_qualifier_phrase_tl + \tl_put_right:NV \l_@@_unit_current_tl \l_@@_tmpa_tl + \tl_set:Nx \l_@@_tmpa_tl + { bracket- \int_use:N \l_@@_unit_int } + \prop_put:NVn \l_@@_unit_prop \l_@@_tmpa_tl { true } + } +\char_set_catcode_active:N \~ +\cs_new_protected:Npn \@@_unit_format_qualifier_space: { + \tl_put_right:Nn \l_@@_unit_current_tl { \text { ~ } } + \tl_put_right:NV \l_@@_unit_current_tl \l_@@_tmpa_tl + \tl_set:Nx \l_@@_tmpa_tl + { bracket- \int_use:N \l_@@_unit_int } + \prop_put:NVn \l_@@_unit_prop \l_@@_tmpa_tl { true } +} +\char_set_catcode_space:N \~ +\cs_new_protected:Npn \@@_unit_format_qualifier_subscript: { + \tl_put_right:Nx \l_@@_unit_current_tl + { \exp_not:N \PrintSubscript { \exp_not:V \l_@@_tmpa_tl } } +} +\cs_new_protected:Npn \@@_unit_format_qualifier_text: { + \tl_put_right:NV \l_@@_unit_current_tl \l_@@_tmpa_tl +} +% \end{macrocode} +%\end{macro} +%\end{macro} +% +% \begin{macro}{\@@_unit_format_sorted:} +% For when the powers are sorted with the positive ones first. The only +% slight issue is making sure that the additional space is included +% between the two units, if needed. +% \begin{macrocode} +\cs_new_protected:Npn \@@_unit_format_sorted: + { + \tl_set:Nx \l_@@_unit_tl + { + \exp_not:V \l_@@_unit_numerator_tl + \bool_lazy_or:nnF + { \tl_if_empty_p:N \l_@@_unit_numerator_tl } + { \tl_if_empty_p:N \l_@@_unit_denominator_tl } + { + \exp_not:N \l_@@_unit_product_tl + } + \exp_not:V \l_@@_unit_denominator_tl + } + } +% \end{macrocode} +% \end{macro} +% +%\begin{macro}{\@@_unit_format_symbol:} +%\begin{macro}{ +% \@@_unit_format_symbol_aux: , +% \@@_unit_format_symbol_aux_alt: +%} +% If there is no symbol, something is wrong! The only exception is +% when the code is inside the \cs{si} function (or similar) and there +% is only a prefix with nothing else present at all. +% \begin{macrocode} +\cs_new_protected:Npn \@@_unit_format_symbol: { + \tl_set:Nx \l_@@_tmpa_tl + { symbol- \int_use:N \l_@@_unit_int } + \prop_get:NVNTF \l_@@_unit_prop \l_@@_tmpa_tl + \l_@@_tmpa_tl + { + \tl_put_right:NV \l_@@_unit_current_tl \l_@@_tmpa_tl + } + { \@@_unit_format_symbol_aux: } +} +\cs_new_protected:Npn \@@_unit_format_symbol_aux: { + \msg_error:nn { siunitx } { prefix-only } +} +\cs_new_protected:Npn \@@_unit_format_symbol_aux_alt: { + \int_compare:nNnTF { \l_@@_unit_int } = { 1 } + { + \prop_remove:Nn \l_@@_unit_prop { prefix-1 } + \prop_remove:Nn \l_@@_unit_prop { prefix-symbol-1 } + \prop_remove:Nn \l_@@_unit_prop { prefix-base-1 } + \prop_remove:Nn \l_@@_unit_prop { total-units } + \prop_if_empty:NF \l_@@_unit_prop + { \msg_error:nn { siunitx } { prefix-only } } + } + { \msg_error:nn { siunitx } { prefix-only } } +} +% \end{macrocode} +%\end{macro} +%\end{macro} +% +%\subsection{Unit output} +% +% A collection of the internal parts of various user functions. +% +%\begin{macro}{\l_@@_multi_brackets_bool} +%\begin{macro}{\l_@@_multi_repeat_bool} +% Flags for multi-part numbers. +% \begin{macrocode} +\bool_new:N \l_@@_multi_brackets_bool +\bool_new:N \l_@@_multi_repeat_bool +% \end{macrocode} +%\end{macro} +%\end{macro} +% +%\begin{macro}{\l_@@_product_brackets_bool} +%\begin{macro}{\l_@@_product_power_bool} +%\begin{macro}{\l_@@_number_unit_repeat_bool} +% Flags for product units. +% \begin{macrocode} +\bool_new:N \l_@@_product_brackets_bool +\bool_new:N \l_@@_product_power_bool +\bool_new:N \l_@@_product_repeat_bool +\bool_new:N \l_@@_number_unit_repeat_bool +% \end{macrocode} +%\end{macro} +%\end{macro} +%\end{macro} +% +%\begin{macro}{\l_@@_number_unit_breaks_bool} +%\begin{macro}{\l_@@_number_unit_product_tl} +% Options for printing units or units with numbers. +% \begin{macrocode} +\keys_define:nn { siunitx } { + allow-number-unit-breaks .bool_set:N = + \l_@@_number_unit_breaks_bool, + multi-part-units .choice:, + multi-part-units + / brackets .code:n = + { + \bool_set_true:N \l_@@_multi_brackets_bool + \bool_set_false:N \l_@@_multi_repeat_bool + }, + multi-part-units + / repeat .code:n = + { + \bool_set_false:N \l_@@_multi_brackets_bool + \bool_set_true:N \l_@@_multi_repeat_bool + }, + multi-part-units + / single .code:n = + { + \bool_set_false:N \l_@@_multi_brackets_bool + \bool_set_false:N \l_@@_multi_repeat_bool + }, + number-unit-product .tl_set:N = + \l_@@_number_unit_product_tl, + number-unit-separator .tl_set:N = + \l_@@_number_unit_product_tl, + product-units .choice:, + product-units + / brackets .code:n = + { + \bool_set_true:N \l_@@_product_brackets_bool + \bool_set_false:N \l_@@_product_power_bool + \bool_set_false:N \l_@@_product_repeat_bool + }, + product-units + / brackets-power .code:n = + { + \bool_set_true:N \l_@@_product_brackets_bool + \bool_set_true:N \l_@@_product_power_bool + \bool_set_false:N \l_@@_product_repeat_bool + }, + product-units + / power .code:n = + { + \bool_set_false:N \l_@@_product_brackets_bool + \bool_set_true:N \l_@@_product_power_bool + \bool_set_false:N \l_@@_product_repeat_bool + }, + product-units + / repeat .code:n = + { + \bool_set_false:N \l_@@_product_brackets_bool + \bool_set_false:N \l_@@_product_power_bool + \bool_set_true:N \l_@@_product_repeat_bool + }, + product-units + / single .code:n = + { + \bool_set_false:N \l_@@_product_brackets_bool + \bool_set_false:N \l_@@_product_power_bool + \bool_set_false:N \l_@@_product_repeat_bool + }, +} +\keys_set:nn { siunitx } { + multi-part-units = brackets, + number-unit-product = \, , + product-units = repeat +} +% \end{macrocode} +%\end{macro} +%\end{macro} +% +%\begin{macro}{\@@_unit_output:nn} +%\begin{macro}{\@@_unit_output:Vn} +% For typesetting a unit directly: used by \cs{si} and the \texttt{s} +% column. The second argument is any options to set locally. +% \begin{macrocode} +\cs_new_protected:Npn \@@_unit_output:nn #1#2 { + \cs_set_eq:NN \@@_unit_format_symbol_aux: + \@@_unit_format_symbol_aux_alt: + \cs_set_eq:NN \@@_unit_format_fraction_symbol_aux_ii: + \@@_unit_format_fraction_symbol_aux_alt: + \@@_unit_in:nn {#1} {#2} + \int_compare:nNnTF { \l_@@_unit_prefix_int } = { 0 } + { + \str_if_eq:VnT \l_@@_per_mode_tl { symbol } + { + \int_compare:nNnT { \l_@@_unit_numerator_int } = { 0 } + { + \bool_if:NT \l_@@_unit_parse_bool + { \@@_print:nn { unit } { 1 } } + } + } + } + { + \tl_set:Nx \l_@@_tmpa_tl + { + \int_use:N \l_@@_unit_prefix_base_int + \exp_not:N \PrintSuperscript + { \int_use:N \l_@@_unit_prefix_int } + } + \@@_print:nV { number } \l_@@_tmpa_tl + \@@_unit_output_number_sep: + } + \@@_print:nV { unit } \l_@@_unit_tl +} +\cs_generate_variant:Nn \@@_unit_output:nn { V } +% \end{macrocode} +%\end{macro} +%\end{macro} +% +%\begin{macro}{\@@_unit_output_number_sep:} +%\begin{macro}{\@@_unit_output_number_sep_aux:} +% For printing the number separator. The \cs{tex_mathchoice:D} code +% deals with the \opt{symbol-or-fraction} setting for \opt{per-mode}, +% as in that case omission of the space between a number and unit +% depends on the current math style. +% \begin{macrocode} +\cs_new_protected:Npn \@@_unit_output_number_sep: { + \bool_if:NTF \l_@@_number_unit_breaks_bool + { \penalty \binoppenalty } { \nobreak } + \bool_if:NTF \l_@@_per_auto_bool + { + \mode_if_math:TF + { + \tex_mathchoice:D + { \l_@@_number_unit_product_tl } + { \@@_unit_output_number_sep_aux: } + { \@@_unit_output_number_sep_aux: } + { \@@_unit_output_number_sep_aux: } + } + { \@@_unit_output_number_sep_aux: } + } + { \@@_unit_output_number_sep_aux: } +} +\cs_new_protected:Npn \@@_unit_output_number_sep_aux: { + \bool_if:NF \l_@@_omit_unit_space_bool + { \l_@@_number_unit_product_tl } +} +% \end{macrocode} +%\end{macro} +%\end{macro} +% +%\begin{macro}{\@@_unit_output_pre_print:} +%\begin{macro}{\@@_unit_output_print:} +% The printing functions for units do some simple tests then +% actually print there output. +% \begin{macrocode} +\cs_new_protected:Npn \@@_unit_output_pre_print: { + \tl_if_empty:NF \l_@@_pre_unit_tl + { + \nobreak + \@@_print:nV { unit } \l_@@_pre_unit_tl + } +} +\cs_new_protected:Npn \@@_unit_output_print: { + \int_compare:nNnF { \l_@@_unit_prefix_int } = { 0 } + { + \tl_set:Nx \l_@@_tmpa_tl + { + \bool_if:NTF \l_@@_tight_bool + { + \exp_not:N \ensuremath + { { \exp_not:V \l_@@_exponent_product_tl } } + } + { + \exp_not:N \ensuremath + { { } \exp_not:V \l_@@_exponent_product_tl { } } + } + \int_use:N \l_@@_unit_prefix_base_int + ^ { \int_use:N \l_@@_unit_prefix_int } + } + \@@_print:nV { number } \l_@@_tmpa_tl + } + \tl_if_empty:NF \l_@@_unit_tl + { + \@@_unit_output_number_sep: + \@@_print:nV { unit } \l_@@_unit_tl + } +} +% \end{macrocode} +%\end{macro} +%\end{macro} +% +%\subsection{Numbers with units} +% +% Numbers with units have to be formatted in a more complex way than +% simply sticking the two together. +% +%\begin{macro}{\l_@@_preunit_tl} +% A pre-unit is optional, so can be handled using the setting system. +% \begin{macrocode} +\keys_define:nn { siunitx } { + preunit .tl_set:N = \l_@@_preunit_tl , +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\l_@@_pre_unit_tl} +% When there is a pre-unit, it gets stored here. +% \begin{macrocode} +\tl_new:N \l_@@_pre_unit_tl +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\l_@@_number_product_int} +% Used to count up the number of product tokens in a number. +% \begin{macrocode} +\int_new:N \l_@@_number_product_int +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\@@_combined:nnnn} +% Printing numbers and units means first processing the units, then +% handing off this information to the combined number and unit +% processor. +% \begin{macrocode} +\cs_new_protected:Npn \@@_combined:nnnn #1#2#3#4 { + \IfNoValueTF {#3} + { \tl_clear:N \l_@@_pre_unit_tl } + { + \group_begin: + \@@_unit_in:nn {#3} {#1} + \cs_set_eq:NN \l_@@_pre_unit_tl \l_@@_unit_tl + \exp_args:NNNo \group_end: + \tl_set:Nn \l_@@_pre_unit_tl { \l_@@_unit_tl } + } + \cs_set_eq:NN \l_@@_brackets_bool + \l_@@_multi_brackets_bool + \@@_combined_unit:nnn {#2} {#4} {#1} + \@@_combined_output:n {#2} +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\@@_combined_output:n} +% Printing the combination of a number and a unit means checking for +% parsing then parsing the number part. +% \begin{macrocode} +\cs_new_protected:Npn \@@_combined_output:n #1 { + \bool_if:NTF \l_@@_number_parse_bool + { + \tl_clear:N \l_@@_number_out_tl + \bool_set_false:N \l_@@_number_compound_bool + \@@_number_output_parse:n {#1} + } + { + \@@_unit_output_pre_print: + \@@_print:nn { number } { \ensuremath {#1} } + \@@_unit_output_print: + } +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\@@_combined_unit:nnn} +% In most cases, sorting out the main unit is easy: simply set up for +% printing using \cs{@@_unit_in:nn}. However, if there are multiple +% parts to the number, and they are to be combined into the unit, then +% there is more work to do. In either case, the result is the +% correctly-prepared unit stored in \cs{l_@@_unit_tl}. +% \begin{macrocode} +\cs_new_protected:Npn \@@_combined_unit:nnn #1#2#3 { + \bool_if:NTF \l_@@_product_power_bool + { + \@@_combined_product_count:n {#1} + \int_compare:nNnTF { \l_@@_number_product_int } > { 0 } + { + \int_incr:N \l_@@_number_product_int + \tl_set:Nn \l_@@_tmpa_tl {#2} + \tl_set:Nx \l_@@_tmpb_tl + { \tothe { \exp_not:V \l_@@_number_product_int } } + \tl_put_right:NV \l_@@_tmpa_tl \l_@@_tmpb_tl + \@@_unit_in:Vn \l_@@_tmpa_tl {#3} + } + { \@@_unit_in:nn {#2} {#3} } + } + { \@@_unit_in:nn {#2} {#3} } +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\@@_combined_product_count:n} +%\begin{macro}{\@@_combined_product_count_aux:n} +% For counting how many products are in a number, so that the unit +% can be adjusted if needed. +% \begin{macrocode} +\cs_new_protected:Npn \@@_combined_product_count:n #1 { + \int_zero:N \l_@@_number_product_int + \tl_set:Nn \l_@@_tmpa_tl {#1} + \tl_map_function:NN \l_@@_input_product_tl + \@@_combined_product_count_aux:N +} +\cs_new_protected:Npn \@@_combined_product_count_aux:N #1 { + \tl_if_in:NnT \l_@@_tmpa_tl {#1} + { + \int_incr:N \l_@@_number_product_int + \tl_remove_once:Nn \l_@@_tmpa_tl {#1} + \@@_combined_product_count_aux:N #1 + } +} +% \end{macrocode} +%\end{macro} +%\end{macro} +% +%\subsection{Lists of numbers} +% +%\begin{macro}{\l_@@_list_brackets_bool} +%\begin{macro}{\l_@@_list_repeat_bool} +% For storing the behaviour of list items with respect to units. +% \begin{macrocode} +\bool_new:N \l_@@_list_brackets_bool +\bool_new:N \l_@@_list_repeat_bool +% \end{macrocode} +%\end{macro} +%\end{macro} +% +%\begin{macro}{\l_@@_list_current_tl} +%\begin{macro}{\l_@@_list_tl} +% Two token list variables used to store the list for output. +% \begin{macrocode} +\tl_new:N \l_@@_list_current_tl +\tl_new:N \l_@@_list_tl +% \end{macrocode} +%\end{macro} +%\end{macro} +% +% \begin{variable} +% { +% \l_@@_list_separator_pair_tl , +% \l_@@_list_separator_final_tl , +% \l_@@_list_separator_tl, +% } +% Settings for lists. +% \begin{macrocode} +\keys_define:nn { siunitx } + { + 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} +% {\@@_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} } > 2 + { + \tl_map_function:nN {#1} \@@_list_numbers_aux_ii:n + \l_@@_list_tl + \l_@@_list_separator_final_tl + \l_@@_list_current_tl + } + { + \int_compare:nNnTF { \tl_count:n {#1} } = 2 + { \@@_list_numbers_aux:nn #1 } + { \@@_combined_output:n #1 } + } + } +\cs_new_protected:Npn \@@_list_numbers_aux_ii:n #1 + { + \tl_if_empty:NTF \l_@@_list_tl + { \tl_set_eq:NN \l_@@_list_tl \l_@@_list_current_tl } + { + \tl_put_right:NV \l_@@_list_tl \l_@@_list_separator_tl + \tl_put_right:NV \l_@@_list_tl \l_@@_list_current_tl + } + \tl_set:Nn \l_@@_list_current_tl { \@@_combined_output:n {#1} } + } +\cs_new_protected:Npn \@@_list_numbers_aux:nn #1#2 + { + \@@_combined_output:n {#1} + \l_@@_list_separator_pair_tl + \@@_combined_output:n {#2} + } +% \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}{\@@_range_numbers_core:nn} +% \begin{macro}{\@@_range_numbers_aux:n} +% A range of numbers. This is more restrictive than the \cs{num} +% function: nothing compound. +% \begin{macrocode} +\cs_new_protected:Npn \@@_range_numbers:nn #1#2 + { + \@@_range_numbers_aux:n {#1} + \l_@@_range_phrase_tl + \@@_range_numbers_aux:n {#2} + } +\cs_new_protected:Npn \@@_range_numbers_aux:n #1 + { + \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 } + { + \cs_if_exist:NT \NC@find@S + { + \newcolumntype { C } [1] + { > { \bcolumn #1 \@nil } #1 < { \ecolumn } } + \cs_set:Npn \@@_tmp:w #1 \NC@do S #2 \q_stop + { \NC@list { #1 #2 } } + \exp_after:wN \@@_tmp:w \tex_the:D \NC@list \q_stop + \cs_undefine:N \NC@find@S + \msg_new:nnn { siunitx } { moved-cellspace-column } + { Column~type~for~cellspace~package~moved~to~'#1'. } + \msg_warning:nnn { siunitx } { moved-cellspace-column } { C } + \ifcellspace@m + \def \env@matrix + { + \hskip -\arraycolsep + \let \@ifnextchar \new@ifnextchar + \array + { + * { \c@MaxMatrixCols } + { > { \bcolumn c \@nil $ } c < { $ \ecolumn } } @ { } + } + } + \fi + } + } + { } +} +% \end{macrocode} +% +%\begin{macro}{\@@_table_rewrite_create:N} +%\begin{macro}{\@@_table_rewrite_create_aux:w} +% The \texttt{s} and \texttt{S} column types are both created using +% the \pkg{array} package, but with the internal macros redefined +% to work with optional argument. First, there is a need to do a +% quick shuffle with the \cs{NC@list} macro. The \pkg{siunitx} +% columns have to be listed first, as otherwise the optional +% arguments do not work correctly. So they are added \enquote{by hand} +% to the appropriate macro. +% \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] [] + { + > { \@@_table_collect_begin:Nn #1 {##1} } + c + < { \@@_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}{\@@_table_collect_begin:Nw} +%\begin{macro}{\@@_table_collect_begin_s:} +%\begin{macro}{\@@_table_collect_begin_S:} +% The collector starts by setting up local options, then clears and +% initialises the storage and testing system. Font detection for the +% \texttt{S} column happens here as this ensures that it is not inside +% a box, which will give the wrong result for \opt{detect-mode}. The +% |\use_i:nn| removes the |\ignorespaces| from the cell preamble. +% In the basic \LaTeXe{} template there is only an |\ignorespaces| +% before the content, but to deal with any other material we use +% a delimited approach. It's important to grab everything up to the +% end of the template-before-|#| to allow the Appendix~D trick to work +% inside the |peek| code. +% \begin{macrocode} +\cs_new_protected:Npn \@@_table_collect_begin:Nn #1#2 + { + \keys_set:nn { siunitx } {#2} + \@@_table_collect_begin:Nw #1 + } +\cs_new_protected:Npn \@@_table_collect_begin:Nw #1#2 \ignorespaces + { \use:c { @@_table_collect_begin_ #1 : } #2 } +\cs_new_protected:Npn \@@_table_collect_begin_s: { + \cs_set_eq:NN \@@_table_collect_token:N + \@@_table_collect_token_s:N + \cs_set_eq:NN \@@_table_print: \@@_table_print_s: + \@@_table_collect_init_s: + \@@_table_collect_get: +} +\cs_new_protected:Npn \@@_table_collect_begin_S: { + \cs_set_eq:NN \@@_table_collect_token:N + \@@_table_collect_token_S:N + \cs_set_eq:NN \@@_table_print: \@@_table_print_S: + \@@_table_collect_init_S: + \@@_detect_font: + \bool_if:NTF \l_@@_number_parse_bool + { \@@_table_collect_get: } + { \@@_table_print_S_direct: } +} +% \end{macrocode} +%\end{macro} +%\end{macro} +%\end{macro} +%\end{macro} +% +%\begin{macro}{\@@_table_collect_braced:n} +% The collection of braced items depends on the column type. So we +% start of with an empty definition. +% \begin{macrocode} +\cs_new_protected:Npn \@@_table_collect_braced:n #1 { } +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\@@_table_collect_expand:N} +%\begin{macro}{\@@_table_collect_expand_math:N} +% The idea here is to expand content if possible. There are a few +% things to note. Only macros which are not long or protected are +% expanded. There is the possibility that the macro may need the +% contents of the pre-numeral part to be executed, for example see +% \cref{tab:xmpl:calc} in the user part of the documentation. +% \begin{macrocode} +\cs_new_protected:Npn \@@_table_collect_expand:N #1 { + \cs_if_eq:NNTF #1 \color + { + \bool_if:NTF \l_@@_table_collect_pre_bool + { + \tl_clear:N \l_@@_number_color_tl + \tl_clear:N \l_@@_unit_color_tl + \tl_put_right:Nn \l_@@_table_collect_pre_tl {#1} + } + { + \bool_set_true:N \l_@@_table_collect_post_bool + \tl_put_right:Nn \l_@@_table_collect_post_tl {#1} + } + } + { + \@@_cs_if_tl:NTF #1 + { + \tl_use:N \l_@@_table_collect_pre_tl + \tl_clear:N \l_@@_table_collect_pre_tl + \cs_set:Npn \@@_table_collect_next: + { \exp_after:wN \@@_table_collect_get: #1 } + } + { + \bool_if:NTF \l_@@_table_collect_pre_bool + { + \tl_put_right:Nn \l_@@_table_collect_pre_tl {#1} + \@@_table_collect_expand_math:N #1 + } + { + \bool_set_true:N \l_@@_table_collect_post_bool + \tl_put_right:Nn \l_@@_table_collect_post_tl {#1} + } + } + } +} +% \end{macrocode} +% There is a need to keep a track of math mode, so that there are no +% disasters when the tokens are boxed up later. The ideal is to know +% the math state of the collected tokens so that appropriate +% steps can be taken to insert math shift tokens later. +% \begin{macrocode} +\cs_new_protected:Npn \@@_table_collect_expand_math:N #1 { + \token_if_math_toggle:NTF #1 + { + \bool_if:NTF \l_@@_table_math_bool + { \bool_set_false:N \l_@@_table_math_bool } + { \bool_set_true:N \l_@@_table_math_bool } + } + { + \cs_if_eq:NNTF #1 \( % \) + { \bool_set_true:N \l_@@_table_math_bool } + { % \( + \cs_if_eq:NNT #1 \) + { \bool_set_false:N \l_@@_table_math_bool } + } + } +} +% \end{macrocode} +%\end{macro} +%\end{macro} +% +%\begin{macro}{\@@_table_collect_get:} +% The token collection system first has to check that the next argument +% does not start with an opening-brace character. If it does, the +% testing is skipped and the braced token is stored. Otherwise, a check +% is made against various ignored tokens. +% \begin{macrocode} +\cs_new_protected:Npn \@@_table_collect_get: + { + \cs_set_eq:NN \@@_table_collect_next: + \@@_table_collect_get: + \peek_catcode_ignore_spaces:NTF \c_group_begin_token + { \@@_table_collect_braced:n } + { \@@_table_collect_not_braced:N } + } +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\@@_table_collect_init:} +% The usual spin-out of basics. +% \begin{macrocode} +\cs_new_protected:Npn \@@_table_collect_init: { + \tl_clear:N \l_@@_table_collect_tl + \tl_clear:N \l_@@_table_collect_pre_tl + \tl_clear:N \l_@@_table_collect_post_tl + \bool_set_false:N \l_@@_table_collect_post_bool + \bool_set_false:N \l_@@_table_math_bool +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\@@_table_collect_init_s:} +%\begin{macro}{\@@_table_collect_init_S:} +% Some type-specific definitions. In the \texttt{S} case, the +% initialisation function for numbers is used to set +% \cs{l_@@_number_valid_tl} correctly. +% \begin{macrocode} +\cs_new_protected:Npn \@@_table_collect_init_s: { + \@@_table_collect_init: + \bool_set_false:N \l_@@_table_collect_pre_bool + \cs_set_protected:Npn \@@_table_collect_braced:n ##1 + { + \tl_put_right:Nn \l_@@_table_collect_tl { {##1} } + \@@_table_collect_next: + } +} +\cs_new_protected:Npn \@@_table_collect_init_S: { + \@@_number_in_init: + \tl_set:Nx \l_@@_number_valid_tl + { + \exp_not:V \l_@@_input_complex_tl + \exp_not:V \l_@@_input_decimal_tl + \exp_not:V \l_@@_input_digit_tl + \exp_not:V \l_@@_input_exponent_tl + \exp_not:V \l_@@_input_ignore_tl + \exp_not:V \l_@@_input_comparator_tl + \exp_not:V \l_@@_input_uncert_close_tl + \exp_not:V \l_@@_input_uncert_open_tl + \exp_not:V \l_@@_input_sign_tl + \exp_not:V \l_@@_input_symbol_tl + } + \bool_set_true:N \l_@@_table_collect_pre_bool + \cs_set_protected:Npn \@@_table_collect_braced:n ##1 + { + \bool_if:NTF \l_@@_table_collect_pre_bool + { \tl_put_right:Nn \l_@@_table_collect_pre_tl { {##1} } } + { + \bool_set_true:N \l_@@_table_collect_post_bool + \tl_put_right:Nn \l_@@_table_collect_post_tl { {##1} } + } + \@@_table_collect_next: + } +} +% \end{macrocode} +%\end{macro} +%\end{macro} +% +%\begin{macro}{\@@_table_collect_next:} +% A holder for the next thing to do. +% \begin{macrocode} +\cs_new_protected:Npn \@@_table_collect_next: { } +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\@@_table_collect_newline:} +% The end macro needs to come before the new line is called. The +% print function is redefined so that it only actually does stuff once. +% As each cell is a group anyway, there is no need to save the +% definition of \cs{@@_table_print:}, as it will re-appear on its +% own. +% \begin{macrocode} +\cs_new_protected:Npn \@@_table_collect_newline: { + \@@_table_print: + \cs_set_eq:NN \@@_table_print: \prg_do_nothing: + \tabularnewline +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\@@_table_collect_end:} +% The same concept applies to the \cs{end} macro. +% \begin{macrocode} +\cs_new_protected:Npn \@@_table_collect_end: { + \@@_table_print: + \cs_set_eq:NN \@@_table_print: \prg_do_nothing: + \end +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\@@_table_collect_not_braced:N} +%\begin{macro}{\@@_table_collect_not_braced_aux_i:N} +%\begin{macro}{\@@_table_collect_not_braced_aux_ii:N} +% A few macros are simply passed through to be executed; this is mainly +% so that the table actually works. The newline function needs its own +% function, which is picked up by hand. +% \begin{macrocode} +\cs_new_protected:Npn \@@_table_collect_not_braced:N #1 + { + \token_if_eq_meaning:NNF #1 \tex_ignorespaces:D + { + \token_if_eq_meaning:NNF #1 \tex_unskip:D + { \@@_table_collect_not_braced_aux_i:N #1 } + } + \@@_table_collect_next: + } +\AtBeginDocument + { + \@ifpackageloaded { mdwtab } + { + \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 + { + \token_if_eq_meaning:NNF #1 \@maybe@unskip + { \@@_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_const:Nn \c_@@_one_fill_skip { 0pt plus 1fill } +% \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 { 0pt plus -0.5fill } + \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 + \c_group_end_token + \@@_table_colortbl_correction: + } + } + } + } +% \end{macrocode} +% +% \subsection{Printing units in \texttt{s} columns} +% +% The easiest type of printing is the \texttt{s} column. Here, there is +% no real problem with alignment. All that has to happen is to print the +% collected input as the argument to the internal part of an \cs{si} +% function. +% +% \begin{variable}{\l_@@_table_unit_align_skip} +% The spacing used is stored as a skip, which needs to be set up first. +% \begin{macrocode} +\skip_new:N \l_@@_table_unit_align_skip +% \end{macrocode} +% \end{variable} +% +% \begin{macrocode} +\keys_define:nn { siunitx } + { + table-unit-alignment .choice:, + table-unit-alignment / + center .code:n = + { + \skip_set:Nn \l_@@_table_unit_align_skip + { 0pt plus 0.5fill } + }, + table-unit-alignment / + left .code:n = + { \skip_set:Nn \l_@@_table_unit_align_skip { \c_zero_skip } }, + table-unit-alignment / + right .code:n = + { + \skip_set:Nn \l_@@_table_unit_align_skip + { 0pt plus 1fill } + } + } +\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 + { 0pt plus 0.5fill } + \cs_set_eq:NN \@@_table_print_S_direct_main: + \@@_table_print_S_direct_reserved: + \cs_set_eq:NN \@@_table_print_S_parsed: + \@@_table_print_S_reserved: + }, + table-number-alignment / + center-decimal-marker .code:n = + { + \skip_set:Nn \l_@@_table_number_align_skip + { 0pt plus 0.5fill } + \cs_set_eq:NN \@@_table_print_S_direct_main: + \@@_table_print_S_direct_centered: + \cs_set_eq:NN \@@_table_print_S_parsed: + \@@_table_print_S_centered: + }, + table-number-alignment / + left .code:n = + { + \skip_zero:N \l_@@_table_number_align_skip + \cs_set_eq:NN \@@_table_print_S_direct_main: + \@@_table_print_S_direct_reserved: + \cs_set_eq:NN \@@_table_print_S_parsed: + \@@_table_print_S_reserved: + }, + table-number-alignment / + right .code:n = + { + \skip_set:Nn \l_@@_table_number_align_skip + { 0pt plus 1fill } + \cs_set_eq:NN \@@_table_print_S_direct_main: + \@@_table_print_S_direct_reserved: + \cs_set_eq:NN \@@_table_print_S_parsed: + \@@_table_print_S_reserved: + }, + table-omit-exponent .bool_set:N = + \l_@@_table_omit_exponent_bool, + table-text-alignment .choice:, + table-text-alignment / + center .code:n = + { + \skip_set:Nn \l_@@_table_text_align_skip + { 0pt plus 0.5fill } + }, + table-text-alignment / + left .code:n = + { \skip_zero:N \l_@@_table_text_align_skip }, + table-text-alignment / + right .code:n = + { + \skip_set:Nn \l_@@_table_text_align_skip + { 0pt plus 1fill } + }, + table-comparator .choice:, + table-comparator / + false .code:n = + { \prop_remove:Nn \l_@@_table_model_prop { comparator } }, + table-comparator / + true .code:n = + { \prop_put:Nnn \l_@@_table_model_prop { comparator } { > } }, + table-comparator .default:n = true, + table-figures-decimal .code:n = + { + \int_compare:nNnTF {#1} = 0 + { + \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} = 0 + { \prop_remove:Nn \l_@@_table_model_prop { exponent-integer } } + { + \prop_put:Nnx \l_@@_table_model_prop { exponent-integer } + { \prg_replicate:nn {#1} { 8 } } + \prop_put:Nnn \l_@@_table_model_prop { exponent } { true } + } + }, + table-figures-integer .code:n = + { + \int_compare:nNnTF {#1} = 0 + { + \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} = 0 + { \prop_remove:Nn \l_@@_table_model_prop { mantissa-uncertainty } } + { + \prop_put:Nnx \l_@@_table_model_prop { mantissa-uncertainty } + { \prg_replicate:nn {#1} { 8 } } + } + }, + table-parse-only .bool_set:N = \l_@@_table_parse_only_bool, + table-space-text-pre .tl_set:N = \l_@@_table_pre_tl, + table-space-text-post .tl_set:N = \l_@@_table_post_tl, + table-sign-exponent .choice:, + table-sign-exponent / true .code:n = + { \prop_put:Nnn \l_@@_table_model_prop { exponent-sign } { - } }, + table-sign-exponent / false .code:n = + { \prop_remove:Nn \l_@@_table_model_prop { exponent-sign } }, + table-sign-exponent .default:n = true, + table-sign-mantissa .choice:, + table-sign-mantissa / true .code:n = + { \prop_put:Nnn \l_@@_table_model_prop { mantissa-sign } { - } }, + table-sign-mantissa / false .code:n = + { \prop_remove:Nn \l_@@_table_model_prop { mantissa-sign } }, + table-sign-mantissa .default:n = true, + } +% \end{macrocode} +% \end{variable} +% +% A meta-choice for all table alignment is also provided. +% \begin{macrocode} +\keys_define:nn { siunitx } + { + table-alignment .meta:n = + { + table-number-alignment = #1, + table-text-alignment = #1, + table-unit-alignment = #1 + } + } +% \end{macrocode} +% +% Another special option. This converts a number format in compacted +% form into the various internal settings needed. +% \begin{macrocode} +\keys_define:nn { siunitx } + { + table-format .code:n = + { + \bool_set_eq:NN \l_@@_process_plus_saved_bool \l_@@_process_plus_bool + \bool_set_true:N \l_@@_process_plus_bool + \@@_number_in_parse:n {#1} + \prop_set_eq:NN \l_@@_table_model_prop \l_@@_number_in_prop + \tl_clear:N \l_@@_tmpa_tl + \prop_get:NnNT \l_@@_number_in_prop { mantissa-integer } + \l_@@_tmpb_tl + { + \tl_set:Nx \l_@@_tmpa_tl + { table-figures-integer = \l_@@_tmpb_tl } + } + \prop_get:NnNT \l_@@_number_in_prop { mantissa-decimal } + \l_@@_tmpb_tl + { + \clist_put_right:Nx \l_@@_tmpa_tl + { table-figures-decimal = \l_@@_tmpb_tl } + } + \prop_get:NnNT \l_@@_number_in_prop { mantissa-uncertainty } + \l_@@_tmpb_tl + { + \clist_put_right:Nx \l_@@_tmpa_tl + { table-figures-uncertainty = \l_@@_tmpb_tl } + } + \prop_if_in:NnTF \l_@@_number_in_prop { mantissa-sign } + { + \clist_put_right:Nn \l_@@_tmpa_tl + { table-sign-mantissa =true } + } + { + \clist_put_right:Nn \l_@@_tmpa_tl + { table-sign-mantissa =false } + } + \prop_get:NnNT \l_@@_number_in_prop { exponent-integer } + \l_@@_tmpb_tl + { + \clist_put_right:Nx \l_@@_tmpa_tl + { table-figures-exponent = \l_@@_tmpb_tl } + } + \prop_if_in:NnTF \l_@@_number_in_prop { exponent-sign } + { + \clist_put_right:Nn \l_@@_tmpa_tl + { table-sign-exponent =true } + } + { + \clist_put_right:Nn \l_@@_tmpa_tl + { table-sign-exponent =false } + } + \clist_put_right:Nn \l_@@_tmpa_tl + { table-number-alignment = center } + \keys_set:nV { siunitx } \l_@@_tmpa_tl + \bool_set_eq:NN \l_@@_process_plus_bool \l_@@_process_plus_saved_bool + } + } +\bool_new:N \l_@@_process_plus_saved_bool +% \end{macrocode} +% +% \begin{macro}{\@@_table_print_S:} +% The main printing function makes a choice depending on whether there is +% any numerical part to print at all. This affects which set of skips to +% insert. Font detection for the \texttt{S} column is included here as +% this is needed to do this work outside of an \cs{hbox}. +% \begin{macrocode} +\cs_new_protected:Npn \@@_table_print_S: + { + \bool_if:NTF \l_@@_table_collect_pre_bool + { + \@@_table_column_begin:n { \l_@@_table_text_align_skip } + \l_@@_table_collect_pre_tl + \@@_table_column_end:n { \l_@@_table_text_align_skip } + } + { + \@@_table_column_begin:n { \l_@@_table_number_align_skip } + \bool_if:NTF \l_@@_table_parse_only_bool + { \@@_table_print_S_no_alignment: } + { \@@_table_print_S_alignment: } + \bool_if:NTF \l_@@_table_align_text_pre_bool + { \@@_table_print_S_pre_aligned: } + { \@@_table_print_S_pre_not_aligned: } + \box_use:N \l_@@_table_result_box + \bool_if:NTF \l_@@_table_align_text_post_bool + { \@@_table_print_S_post_aligned: } + { \@@_table_print_S_post_not_aligned: } + \@@_table_column_end:n { \l_@@_table_number_align_skip } + } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_table_print_S_no_alignment:} +% With no alignment to do, the code can be pretty simple. The collected +% number is simply printed between the two non-numerical parts. +% \begin{macrocode} +\cs_new_protected:Npn \@@_table_print_S_no_alignment: + { + \l_@@_table_collect_pre_tl + \@@_number_output:V \l_@@_table_collect_tl + \l_@@_table_collect_post_tl + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_table_print_S_alignment:} +% This is a pass-through, so that the appropriate alignment mode is +% retained without needing to retest on each use. +% \begin{macrocode} +\cs_new_protected:Npn \@@_table_print_S_alignment: + { \@@_table_print_S_parsed: } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_table_print_S_parse:} +% A modified version of the number parser for tables. +% \begin{macrocode} +\cs_new_protected:Npn \@@_table_print_S_parse: + { + \bool_set_false:N \l_@@_error_bool + \@@_number_in_parse:V \l_@@_table_collect_tl + \bool_if:NF \l_@@_error_bool + { + \bool_if:NTF \l_@@_table_omit_exponent_bool + { + \bool_set_true:N \l_@@_process_fixed_bool + \@@_number_process: + \prop_remove:Nn \l_@@_number_in_prop { exponent } + \prop_remove:Nn \l_@@_number_in_prop { exponent-integer } + } + { \@@_number_process: } + \@@_number_format: + \@@_number_output_color: + } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_table_print_S_measure:NN} +% A short routine to measure up whatever has been extracted from the +% storage system. Boxing up is avoided for the empty cases, as this saves +% a little time(the print routine is relatively slow). +% \begin{macrocode} +\cs_new_protected:Npn \@@_table_print_S_measure:NN #1#2 + { + \tl_if_empty:NTF #1 + { \dim_zero:N #2 } + { + \group_begin: + \hbox_set:Nn \l_@@_tmp_box + { \@@_print:nV { number } #1 } + \exp_args:NNNo \group_end: + \dim_set:Nn #2 { \dim_use:N \box_wd:N \l_@@_tmp_box } + } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro} +% { +% \@@_table_print_S_pre_aligned: , +% \@@_table_print_S_pre_not_aligned: , +% \@@_table_print_S_post_aligned: , +% \@@_table_print_S_post_not_aligned: +% } +% The non-numerical material is inserted along with the filler needed +% to maintain alignment. The order in which the two are inserted depends +% on whether those parts are also aligned. +% \begin{macrocode} +\cs_new_protected:Npn \@@_table_print_S_pre_aligned: + { + \box_use:N \l_@@_table_pre_box + \hbox_to_wd:nn { \l_@@_table_fill_pre_dim } { \tex_hfil:D } + } +\cs_new_protected:Npn \@@_table_print_S_pre_not_aligned: + { + \hbox_to_wd:nn { \l_@@_table_fill_pre_dim } { \tex_hfil:D } + \box_use:N \l_@@_table_pre_box + } +\cs_new_protected:Npn \@@_table_print_S_post_aligned: + { + \hbox_to_wd:nn { \l_@@_table_fill_post_dim } { \tex_hfil:D } + \box_use:N \l_@@_table_post_box + } +\cs_new_protected:Npn \@@_table_print_S_post_not_aligned: + { + \box_use:N \l_@@_table_post_box + \hbox_to_wd:nn { \l_@@_table_fill_post_dim } { \tex_hfil:D } + } +% \end{macrocode} +% \end{macro} +% +% \subsection{Printing the \texttt{S} column with the decimal marker centred} +% +% \begin{macro}{\@@_table_print_S_centered:} +% The main routine for decimal-centred alignment works by boxing up the +% entire output, the integer part and the decimal marker. It then works +% out which part is bigger and calculates the fill correction accordingly. +% Once all of that is done, the various boxes and fill can be inserted. +% \begin{macrocode} +\cs_new_protected:Npn \@@_table_print_S_centered: + { + \@@_table_print_S_centered_ends: + \bool_if:NT \l_@@_table_math_bool { \c_math_toggle_token } + \@@_table_print_S_parse: + \bool_if:NF \l_@@_error_bool + { + \@@_table_print_S_centered_measure: + \bool_if:NT \l_@@_table_math_bool { \c_math_toggle_token } + \dim_set:Nn \l_@@_table_fill_pre_dim + { + \l_@@_table_result_dim + - \l_@@_table_integer_dim + - \l_@@_table_marker_dim + } + \dim_compare:nNnTF \l_@@_table_integer_dim > + \l_@@_table_fill_pre_dim + { \@@_table_print_S_centered_integer: } + { \@@_table_print_S_centered_decimal: } + } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_table_print_S_centered_ends:} +% To deal with the material outside of the number, the first step is to +% box up both parts. If the pre-numeral part has no width, the tokens are +% inserted into the input stream to cover cases where they make a change +% to the colour, font or so forth. After that, the narrower of the two +% boxes is made the same size as the wider: this maintains the alignment. +% \begin{macrocode} +\cs_new_protected:Npn \@@_table_print_S_centered_ends: + { + \hbox_set:Nn \l_@@_table_pre_box + { + { + \l_@@_table_collect_pre_tl + \bool_if:NT \l_@@_table_math_bool + { + \scan_stop: + \c_math_toggle_token + } + } + } + \dim_compare:nNnT + { \box_wd:N \l_@@_table_pre_box } = \c_zero_dim + { + \box_clear:N \l_@@_table_pre_box + \l_@@_table_collect_pre_tl + \bool_set_false:N \l_@@_font_set_bool + } + \hbox_set:Nn \l_@@_table_post_box + { + \bool_if:NT \l_@@_table_math_bool + { + \c_math_toggle_token + \scan_stop: + } + \l_@@_table_collect_post_tl + } + \dim_compare:nNnTF + { \box_wd:N \l_@@_table_pre_box } > + { \box_wd:N \l_@@_table_post_box } + { + \hbox_set_to_wd:Nnn \l_@@_table_post_box + { \box_wd:N \l_@@_table_pre_box } + { + \hbox_unpack:N \l_@@_table_post_box + \tex_hfil:D + } + } + { + \hbox_set_to_wd:Nnn \l_@@_table_pre_box + { \box_wd:N \l_@@_table_post_box } + { + \tex_hfil:D + \hbox_unpack:N \l_@@_table_pre_box + } + } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_table_print_S_centered_measure:} +% \begin{macro} +% { +% \@@_table_print_S_centered_measure_int_part: , +% \@@_table_print_S_centered_measure_marker: , +% \@@_table_print_S_centered_measure_result: +% } +% Here, there are three parts of the number to measure: the integer part, +% the decimal marker and the entire number. Most of the work consists +% of collecting up parts of the number. +% \begin{macrocode} +\cs_new_protected:Npn \@@_table_print_S_centered_measure: + { + \@@_table_print_S_centered_measure_int_part: + \@@_table_print_S_centered_measure_marker: + \@@_table_print_S_centered_measure_result: + } +\cs_new_protected:Npn \@@_table_print_S_centered_measure_int_part: + { + \prop_get:NnNF \l_@@_number_out_prop { comparator } \l_@@_tmpa_tl + { \tl_clear:N \l_@@_tmpa_tl } + \prop_get:NnNT \l_@@_number_out_prop { mantissa-sign } + \l_@@_tmpb_tl + { \tl_put_right:No \l_@@_tmpa_tl \l_@@_tmpb_tl } + \prop_get:NnNT \l_@@_number_out_prop { mantissa-integer } + \l_@@_tmpb_tl + { \tl_put_right:No \l_@@_tmpa_tl \l_@@_tmpb_tl } + \@@_table_print_S_measure:NN \l_@@_tmpa_tl + \l_@@_table_integer_dim + } +\cs_new_protected:Npn \@@_table_print_S_centered_measure_marker: + { + \@@_table_print_S_measure:NN \l_@@_output_decimal_tl + \l_@@_table_marker_dim + } +% \end{macrocode} +% As the overall result will be needed later, the boxing up here is done +% using a named box that will be retained. +% \begin{macrocode} +\cs_new_protected:Npn \@@_table_print_S_centered_measure_result: + { + \prop_get:NnN \l_@@_number_out_prop { result } \l_@@_tmpa_tl + \hbox_set:Nn \l_@@_table_result_box + { \@@_print:nV { number } \l_@@_tmpa_tl } + \dim_set:Nn \l_@@_table_result_dim + { \box_wd:N \l_@@_table_result_box } + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro} +% { +% \@@_table_print_S_centered_integer: , +% \@@_table_print_S_centered_decimal: +% } +% The appropriate place to insert the fill is determined by whether the +% integer or decimal part of the number is bigger. Two dimensions are +% therefore set, for fill before the number and after it. One of these +% will always be zero. +% \begin{macrocode} +\cs_new_protected:Npn \@@_table_print_S_centered_integer: + { + \dim_set:Nn \l_@@_table_fill_post_dim + { \l_@@_table_integer_dim - \l_@@_table_fill_pre_dim } + \dim_zero:N \l_@@_table_fill_pre_dim + } +\cs_new_protected:Npn \@@_table_print_S_centered_decimal: + { + \dim_sub:Nn \l_@@_table_fill_pre_dim + { \l_@@_table_integer_dim } + \dim_zero:N \l_@@_table_fill_post_dim + } +% \end{macrocode} +% \end{macro} +% +% \subsection{Printing the \texttt{S} column with space reserved} +% +% \begin{macro}{\@@_table_print_S_reserved:} +% The procedure for inserting a number with space reserved requires a model +% for each part of the number. +% \begin{macrocode} +\cs_new_protected:Npn \@@_table_print_S_reserved: + { + \@@_table_print_S_reserved_init: + \@@_table_print_S_reserved_ends: + \bool_if:NT \l_@@_table_auto_round_bool + { \@@_table_print_S_reserved_round_auto: } + \@@_table_print_S_parse: + \bool_if:NF \l_@@_error_bool + { + \bool_if:NT \l_@@_table_math_bool { \c_math_toggle_token } + \@@_table_print_S_reserved_comparator: + \@@_table_print_S_reserved_mantissa: + \@@_table_print_S_reserved_exponent: + \bool_if:NT \l_@@_table_math_bool { \c_math_toggle_token } + } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_table_print_S_reserved_init:} +% The creation of a model for the cell to follow. Creation of the finalised +% model is done here so that all of the other options will apply without +% needing complex internal tracking. +% \begin{macrocode} +\cs_new_protected:Npn \@@_table_print_S_reserved_init: + { + \dim_zero:N \l_@@_table_fill_mid_dim + \dim_zero:N \l_@@_table_fill_post_dim + \prop_set_eq:NN \l_@@_number_in_prop \l_@@_table_model_prop + \@@_number_process_sign: + \@@_number_process_zero_fill: + \@@_number_process_mantissa: + \prop_if_in:NnF \l_@@_number_in_prop { symbolic } + { \@@_number_process_uncertainty: } + \@@_number_format: + \prop_get:NnNT \l_@@_table_model_prop { mantissa-decimal-raw } + \l_@@_tmpa_tl + { + \prop_put:NnV \l_@@_number_out_prop { mantissa-decimal-raw } + \l_@@_tmpa_tl + } + \prop_set_eq:NN \l_@@_table_model_prop \l_@@_number_out_prop + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_table_print_S_reserved_ends:} +% The end material here is boxed up into the space already reserved. +% That means doing two boxing ups: one for the model, and one for the +% real thing. As in the centred case, if the pre-numeral part has no +% width then the tokens are inserted \enquote{as is}. To avoid any issues +% with people forgetting to reserve space for the pre-numeral part, it is +% boxed up first at natural width so that the measurement is accurate. +% \begin{macrocode} +\cs_new_protected:Npn \@@_table_print_S_reserved_ends: + { + \hbox_set:Nn \l_@@_table_pre_box + { + { + \l_@@_table_collect_pre_tl + \bool_if:NT \l_@@_table_math_bool + { + \scan_stop: + \c_math_toggle_token + } + } + } + \dim_compare:nNnT + { \box_wd:N \l_@@_table_pre_box } = \c_zero_dim + { + \box_clear:N \l_@@_table_pre_box + \l_@@_table_collect_pre_tl + \bool_set_false:N \l_@@_font_set_bool + } + \hbox_set:Nn \l_@@_tmp_box { { \l_@@_table_pre_tl } } + \hbox_set_to_wd:Nnn \l_@@_table_pre_box + { \box_wd:N \l_@@_tmp_box } + { + \tex_hfil:D + \hbox_unpack:N \l_@@_table_pre_box + } + \hbox_set:Nn \l_@@_tmp_box { \l_@@_table_post_tl } + \hbox_set_to_wd:Nnn \l_@@_table_post_box + { \box_wd:N \l_@@_tmp_box } + { + { + \bool_if:NT \l_@@_table_math_bool + { + \c_math_toggle_token + \scan_stop: + } + \l_@@_table_collect_post_tl + } + \tex_hfil:D + } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_table_print_S_reserved_round_auto:} +% For auto-rounding, the approach is to find how many decimal digits are +% allowed for, and if there are none to simply set the rounding value to +% zero. +% \begin{macrocode} +\cs_new_protected:Npn \@@_table_print_S_reserved_round_auto: + { + \prop_get:NnNTF \l_@@_table_model_prop { mantissa-decimal-raw } + \l_@@_tmpa_tl + { \int_set:Nn \l_@@_process_precision_int { \l_@@_tmpa_tl } } + { \int_zero:N \l_@@_process_precision_int } + \tl_set:Nn \l_@@_round_tl { places } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_table_print_S_reserved_comparator:} +% The comparator is quite simple to deal with. Assuming that there is a +% comparator in the model, this is measured for the reserved width. The +% real comparator can then simply be typeset in a box of the same size. +% If there is no comparator in the real case, then the space added to +% that for filling: this is needed so that any pre-note can be aligned +% freely. +% \begin{macrocode} +\cs_new_protected:Npn \@@_table_print_S_reserved_comparator: + { + \prop_get:NnNTF \l_@@_table_model_prop { comparator } + \l_@@_tmpa_tl + { + \hbox_set:Nn \l_@@_tmp_box + { \@@_print:nV { number } \l_@@_tmpa_tl } + \prop_get:NnNTF \l_@@_number_out_prop { comparator } + \l_@@_tmpa_tl + { + \hbox_set_to_wd:Nnn \l_@@_table_result_box + { \box_wd:N \l_@@_tmp_box } + { \@@_print:nV { number } \l_@@_tmpa_tl } + } + { + \dim_add:Nn \l_@@_table_fill_pre_dim + { \box_wd:N \l_@@_tmp_box } + \cs_set_eq:NN \@@_table_print_S_reserved_store_fill:n + \@@_table_print_S_reserved_store_fill_pre:n + } + } + { + \cs_set_eq:NN \@@_table_print_S_reserved_store_fill:n + \@@_table_print_S_reserved_store_fill_pre:n + \prop_if_in:NnT \l_@@_number_out_prop { comparator } + { + \msg_error:nnx { siunitx } { table-partial-number } + { a~comparator } + } + } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro} +% { +% \@@_table_print_S_reserved_store_fill_pre:n , +% \@@_table_print_S_reserved_store_fill_mid:n +% } +% To allow for the various alignment options, fill is stored in a +% flexible way. +% \begin{macrocode} +\cs_new_protected:Npn \@@_table_print_S_reserved_store_fill_pre:n + { \dim_add:Nn \l_@@_table_fill_pre_dim } +\cs_new_protected:Npn \@@_table_print_S_reserved_store_fill_mid:n + { \dim_add:Nn \l_@@_table_fill_mid_dim } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_table_print_S_reserved_mantissa:} +% \begin{macro} +% { +% \@@_table_print_S_reserved_mantissa_parts: , +% \@@_table_print_S_reserved_mantissa_integer: +% } +% The mantissa of a number may contain a sign, an integer part, a +% decimal marker, a decimal part and a non-separated uncertainty. That +% means that there are two ways to deal with the alignment. Each part +% could be done separately, or a correction can be made after setting +% the combined mantissa. Here, the later approach is taken. The first +% step is to deal with the mantissa as a whole: work out show much space +% to reserve, and see if there is anything at all to put in it. The +% complexity only starts if there is a mantissa in the current cell. +% \begin{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} +% { +% \@@_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:} +% \begin{macro}{\@@_table_print_S_direct_text:n} +% Test to see if the very first item +% in the cell is a |{|. If it is, then we use the same approach as for +% parsed columns and set the material as text. Otherwise, switch to math +% mode and hand off to the main routine. +% \begin{macrocode} +\cs_new_protected:Npn \@@_table_print_S_direct: + { + \peek_catcode_ignore_spaces:NTF \c_group_begin_token + { \@@_table_print_S_direct_text:n } + { \@@_table_print_S_direct_main: } + } +\cs_new_protected:Npn \@@_table_print_S_direct_text:n #1 + { + \@@_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_begin:, +% \@@_table_print_S_direct_centered_end: +% } +% \begin{macro}{\@@_table_print_S_direct_centered_aux:N} +% When centring the content about a decimal marker, the trick is +% to collect everything into two boxes and then compare the sizes. +% In that sense this is very similar to the normal method, except that +% it will work with non-numerical input. +% \begin{macrocode} +\cs_new_protected:Npn \@@_table_print_S_direct_centered: + { + \cs_set_eq:NN \@@_table_print: + \@@_table_print_S_direct_centered_end: + \hbox_set:Nn \l_@@_tmp_box + { \ensuremath { \l_@@_output_decimal_tl } } + \hbox_set_to_wd:Nnn \l_@@_table_post_box + { \box_wd:N \l_@@_tmp_box } + { \tex_hfil:D } + \hbox_set:Nw \l_@@_table_pre_box + \c_math_toggle_token + \tl_map_function:NN \l_@@_input_decimal_tl + \@@_table_print_S_direct_centered_aux:N + } +\cs_new_protected:Npn \@@_table_print_S_direct_centered_aux:N #1 + { + \char_set_active_eq:NN #1 \@@_table_print_S_direct_centered_begin: + \char_set_mathcode:nn { `#1 } { "8000 } + } +\cs_new_protected:Npn \@@_table_print_S_direct_centered_begin: + { + \c_math_toggle_token + \hbox_set_end: + \hbox_set:Nw \l_@@_table_post_box + \c_math_toggle_token + \l_@@_output_decimal_tl + } +\cs_new_protected:Npn \@@_table_print_S_direct_centered_end: + { + \c_math_toggle_token + \hbox_set_end: + \dim_compare:nNnTF + { \box_wd:N \l_@@_table_pre_box } > + { \box_wd:N \l_@@_table_post_box } + { + \hbox_set_to_wd:Nnn \l_@@_table_post_box + { \box_wd:N \l_@@_table_pre_box } + { + \hbox_unpack:N \l_@@_table_post_box + \tex_hfil:D + } + } + { + \hbox_set_to_wd:Nnn \l_@@_table_pre_box + { \box_wd:N \l_@@_table_post_box } + { + \tex_hfil:D + \hbox_unpack:N \l_@@_table_pre_box + } + } + \box_use:N \l_@@_table_pre_box + \box_use:N \l_@@_table_post_box + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro} +% { +% \@@_table_print_S_direct_reserved: , +% \@@_table_print_S_direct_reserved_begin:, +% \@@_table_print_S_direct_reserved_end: +% } +% \begin{macro}{\@@_table_print_S_direct_reserved_aux:N} +% The plan here is to box up the entire number using the information +% available about the size of the two parts. Relatively easy, +% but needs a bit of measuring. The first box here does need to use +% \cs{tex_hill:D} as \texttt{fil} glue will not work. +% \begin{macrocode} +\cs_new_protected:Npn \@@_table_print_S_direct_reserved: + { + \cs_set_eq:NN \@@_table_print: + \@@_table_print_S_direct_reserved_end: + \prop_get:NnNF \l_@@_table_model_prop { mantissa-integer } + \l_@@_tmpa_tl + { \tl_clear:N \l_@@_tmpa_tl } + \hbox_set:Nn \l_@@_tmp_box + { + \ensuremath + { + \prop_get:NnNT \l_@@_table_model_prop { mantissa-sign } + \l_@@_tmpb_tl + { \l_@@_tmpb_tl } + \l_@@_tmpa_tl + } + } + \dim_set:Nn \l_@@_table_integer_dim + { \box_wd:N \l_@@_tmp_box } + \prop_get:NnNF \l_@@_table_model_prop { mantissa-decimal } + \l_@@_tmpa_tl + { \tl_clear:N \l_@@_tmpa_tl } + \hbox_set:Nn \l_@@_tmp_box + { + \ensuremath + { + \l_@@_output_decimal_tl + \l_@@_tmpa_tl + } + } + \hbox_set_to_wd:Nnn \l_@@_table_post_box + { \box_wd:N \l_@@_tmp_box } + { \tex_hfil:D } + \tex_setbox:D \l_@@_table_pre_box \tex_hbox:D to \l_@@_table_integer_dim + \c_group_begin_token + \c_math_toggle_token + \tl_map_function:NN \l_@@_input_decimal_tl + \@@_table_print_S_direct_reserved_aux:N + \tex_hfill:D + } +\cs_new_protected:Npn \@@_table_print_S_direct_reserved_aux:N #1 + { + \char_set_active_eq:NN #1 \@@_table_print_S_direct_reserved_begin: + \char_set_mathcode:nn { `#1 } { "8000 } + } +\cs_new_protected:Npn \@@_table_print_S_direct_reserved_begin: + { + \c_math_toggle_token + \c_group_end_token + \tex_setbox:D \l_@@_table_post_box \tex_hbox:D to \box_wd:N \l_@@_tmp_box + \c_group_begin_token + \c_math_toggle_token + \l_@@_output_decimal_tl + } +\cs_new_protected:Npn \@@_table_print_S_direct_reserved_end: + { + \c_math_toggle_token + \tex_hfil:D + \c_group_end_token + \@@_table_align_left:n { \l_@@_table_number_align_skip } + \box_use:N \l_@@_table_pre_box + \box_use:N \l_@@_table_post_box + \@@_table_align_right:n { \l_@@_table_number_align_skip } + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \subsection{Table settings} +% +% To allow for the construction above, the table settings are given here. +% +% \begin{macrocode} +\keys_set:nn { siunitx } + { + table-align-comparator = true, + table-align-exponent = true, + table-align-text-pre = true, + table-align-text-post = true, + table-align-uncertainty = true, + table-omit-exponent = false, + table-parse-only = false, + table-number-alignment = center-decimal-marker, + table-text-alignment = center, + table-figures-decimal = 2, + table-figures-integer = 3 + } +% \end{macrocode} +% +%\subsection{Symbols} +% +% Not all units use letters alone for their symbol. This raises two +% problems. First, the symbols need to work in math and in text mode. +% Second, the user needs to be able to adjust each symbol. +% +%\begin{macro}{\l_@@_redefine_symbols_bool} +% Only one setting applies here! +% \begin{macrocode} +\keys_define:nn { siunitx } + { redefine-symbols .bool_set:N = \l_@@_redefine_symbols_bool } +\keys_set:nn { siunitx } { redefine-symbols = true } +% \end{macrocode} +%\end{macro} +% +% The redefinition of symbols has to do a number of checks to ensure +% that there are no clashes. +% \begin{macrocode} +\AtBeginDocument + { + \bool_if:NT \l_@@_redefine_symbols_bool + { + \@ifpackageloaded { 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 { \g_@@_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 { \g_@@_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 \@@_unit_mathrm:n { C } , + math-degree = { } ^ { \circ }, + math-micro = \text { \c_@@_mu_tl }, + math-ohm = \text { \ensuremath { \g_@@_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 C , + text-degree = \ensuremath { { } ^ { \circ } }, + text-micro = \c_@@_mu_tl , + text-ohm = \ensuremath { \g_@@_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 } + { + \use:c + { + l__@@_ + \str_fold_case:n {#1} + _ + \mode_if_math:TF { math } { text } + _tl + } + } + } +% \end{macrocode} +% \end{macro} +% +%\begin{macro}{\SIUnitSymbolAngstrom} +%\begin{macro}{\SIUnitSymbolArcminute} +%\begin{macro}{\SIUnitSymbolArcsecond} +%\begin{macro}{\SIUnitSymbolCelsius} +%\begin{macro}{\SIUnitSymbolDegree} +%\begin{macro}{\SIUnitSymbolMicro} +%\begin{macro}{\SIUnitSymbolOhm} +% The wrapper macros are created. +% \begin{macrocode} +\@@_symbol_new:n { Angstrom } +\@@_symbol_new:n { Arcminute } +\@@_symbol_new:n { Arcsecond } +\@@_symbol_new:n { Celsius } +\@@_symbol_new:n { Degree } +\@@_symbol_new:n { Micro } +\@@_symbol_new:n { Ohm } +% \end{macrocode} +%\end{macro} +%\end{macro} +%\end{macro} +%\end{macro} +%\end{macro} +%\end{macro} +%\end{macro} +% +% \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. +% Technically, we should hae a different slot for micro than for a mu, but +% for the broadest compatibility we go with the latter. +% The single degree Celsius symbol is a compatibility character, and so +% the two separate glyphs \enquote{degree} and \enquote{C} are used. +% \begin{macrocode} +\AtBeginDocument + { + \@ifpackageloaded { fontspec } + { + \int_const:Nn \c_@@_degree_int { 176 } + \int_const:Nn \c_@@_micro_int { "000B5 } + \int_const:Nn \c_@@_angstrom_int { "0212B } + \int_const:Nn \c_@@_ohm_int { "003A9 } + \sys_if_engine_xetex:T + { + \@@_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 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 { \g_@@_omega_tl } } } + { \tex_char:D \c_@@_ohm_int } + \sys_if_engine_xetex:T + { + \@@_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 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 { \g_@@_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 - 1 } + } + \bool_lazy_or:nnF + { \l_@@_group_decimal_bool } { \l_@@_group_integer_bool } + { + \clist_put_right:Nn \l_@@_pgf_link_clist + { min~exponent~for~1000~sep = 999 } + } + \bool_if:NTF \l_@@_process_integer_zero_bool + { + \clist_put_right:Nn \l_@@_pgf_link_clist + { skip~0. = false } + } + { + \clist_put_right:Nn \l_@@_pgf_link_clist + { skip~0. = true } + } + \str_if_eq:VnTF \l_@@_process_sign_tl { + } + { + \clist_put_right:Nn \l_@@_pgf_link_clist + { showpos = true } + } + { + \clist_put_right:Nn \l_@@_pgf_link_clist + { showpos = false } + } + \use:x + { + \exp_not:N \pgfqkeys + { /pgf/number~format } + { \exp_not:V \l_@@_pgf_link_clist } + } +} +% \end{macrocode} +%\end{macro} +%\end{macro} +% +%\subsection{Messages} +% +% Lots of messages, all of them together in one block to make life +% easier. +% \begin{macrocode} +\msg_new:nnnn { siunitx } { bad-arc-sign } + { Incorrect~use~of~sign~in~degree-minute-second~angle. } + { Only~the~highest~value~part~of~an~angle~can~have~a~sign. } +\msg_new:nnnn { siunitx } { color-not-loaded } + { Package~"color"~not~loaded. } + { The~command~\token_to_str:N \color \ is~not~available. } +\msg_new:nnnn { siunitx } { duplicate-complex-root-token } + { Duplicate~complex~root~token~'#1'~in~input. } + { Only~one~complex~root~token~can~appear~in~a~single~number. } +\msg_new:nnnn { siunitx } { duplicate-decimal-token } + { Duplicate~decimal~marker~token~'#1'~in~input. } + { Only~one~decimal~marker~token~can~appear~in~a~single~number. } +\msg_new:nnnn { siunitx } { duplicate-exponent-token } + { Duplicate~exponent~marker~token~'#1'~in~input. } + { Only~one~exponent~marker~token~can~appear~in~a~single~number. } +\msg_new:nnnn { siunitx } { duplicate-quotient-token } + { Duplicate~quotient~token. } + { Only~one~quotient~token~can~appear~in~a~single~number. } +\msg_new:nnnn { siunitx } { duplicate-sticky-per } + { Duplicate~\token_to_str:N \per. } + { + When~the~'sticky-per'~option~is~active,~only~one + \token_to_str:N \per may~appear~in~a~unit. + } +\msg_new:nnnn { siunitx } { empty-arc } + { Empty~degree-minute-second~angle. } + { The~angle~given~does~not~contain~any~numbers. } +\msg_new:nnnn { siunitx } { empty-uncertainty } + { Empty~uncertainty~given~in~'#1'. } + { The~number~given~contains~an~empty~uncertainty. } +\msg_new:nnnn { siunitx } { ending-product-token } + { Misplaced~product~token. } + { A~number~cannot~end~with~a~product~token. } +\msg_new:nnnn { siunitx } { ending-quotient-token } + { Misplaced~quotient~token. } + { A~number~cannot~end~with~a~quotient~token. } +\msg_new:nnnn { siunitx } { invalid-arc-format } + { Invalid~degree-minute-second angle~'#1'. } + { + Angles~given~in~degree-minute-second~format~should~contain~two~';' + symbols~to~divide~up~the~parts~of~the~input. + } +\msg_new:nnnn { siunitx } { invalid-number } + { Invalid~numerical~input~'#1'. } + { + The~input~given~as~a~number~does~not~make~logical~sense.~ + This~happens,~for~example,~if~a~number~only~contains~a~sign. + } +\msg_new:nnnn { siunitx } { invalid-token-in-exponent } + { Invalid~exponent~in~numerical~input~'#1'. } + { + The~exponent~part~of~a~number~cannot~contain~an~uncertainty~or~ + complex~part: \\ + the~input~given~appears~to~contain~one~of~these~in~the~exponent. + } +\msg_new:nnnn { siunitx } { invalid-token-in-number } + { Invalid~token~'#1'~in~numerical~input. } + { + Numbers~can~only~contain~tokens~defined~using~the~ + 'input-...'~options:\\ + the~token~'#1'~is~not~set~up~as~a~valid~part~of~a~number. + } +\msg_new:nnnn { siunitx } { invalid-token-in-uncertainty } + { Invalid~uncertainty~in~numerical~input~'#1'. } + { + The~uncertainty~part~of~a~number~may~only~contain~digits~or~ + symbols. + } +\msg_new:nnnn { siunitx } { literal-unit } + { Literal~units~disabled. } + { + You~gave~the~literal~input~'#1'~ + but~literal~unit~output~is~disabled. + } +\msg_new:nnnn { siunitx } { misplaced-sign-token } + { Misplaced~sign~token~'#1'. } + { Sign~tokens~can~only~come~at~the~beginning~of~a~number. } +\msg_new:nnnn { siunitx } { misplaced-complex-root-token } + { Misplaced~complex~token~in~numerical~input~'#1'. } + { + The~root~token~must~come~either~before~or~after~the~real~digits~ + of~the~complex~part. + } +\msg_new:nnnn { siunitx } { misplaced-uncertainty-token } + { Misplaced~uncertainty~token~'#1'. } + { + The~uncertainty~in~a~number~must~be~given~between~a~set~of~ + delimiters~as~defined~by~the\\ + \ \ 'input-open-uncertainty'~and~'input-close-uncertainty'~ + options. + } +\msg_new:nnnn { siunitx } { multi-part-range } + { Numerical~range~with~multiple~parts. } + { + The~input~'#1'~is~a~number~which~has~more~than~one~part: \\ + ranges~can~only~contain~one~number~in~each~part. + } +\msg_new:nnn { siunitx } { non-convertible-exponent } + { Exponent~'#1'~cannot~be~converted~into~a~symbolic~prefix. } +\msg_new:nnn { siunitx } { option-not-available } + { Option~'#1'~not~available~in~strict~mode. } +\msg_new:nnn { siunitx } { option-preamble-only } + { Option~'#1'~only~available~in~the~preamble. } +\msg_new:nnnn { siunitx } { prefix-base-mismatch } + { Prefix~bases~do~not~match. } + { + You~have~asked~for~prefixes~to~be~converted~into~a~power,~ + but~the~bases~do~not~match. + } +\msg_new:nnn { siunitx } { prefix-only } + { Prefix~with~no~unit. } +\msg_new:nnnn { siunitx } { qualifier-before-unit } + { Qualifier~before~unit. } + { Unit~qualifiers~have~to~follow~after~units,~not~before~them. } +\msg_new:nnnn { siunitx } { restricted-number } + { Token~'#1'~forbidden~in~restricted~numerical~input. } + { + The~current~input~must~be~a~real~number~and~cannot~contain: \\ + \ -~an~exponent; \\ + \ -~an~uncertainty; \\ + \ -~a~complex~part. + } +\msg_new:nnnn { siunitx } { starting-product-token } + { Misplaced~product~token. } + { A~number~cannot~begin~with~a~product~token. } +\msg_new:nnnn { siunitx } { starting-quotient-token } + { Misplaced~quotient~token. } + { A~number~cannot~begin~with~a~quotient~token. } +\msg_new:nnnn { siunitx } { table-partial-number } + { No~space~reserved~for~#1~\msg_line_context:. } + { + The~number~in~the~current~table~cell~contains~#1~part, + but~you~did~not~reserve~any~space~to~print~it: \\ + it~will~be~missing~in~the~output. + } +\msg_new:nnnn { siunitx } { unknown-option } + { Unknown~option~'#1'. } + { + The~option~file~'#1'~is~not~known~by~siunitx: + perhaps~it~is~spelled~incorrectly. + } +\msg_new:nnnn { siunitx } { version-1-option } + { Version~1~option~'#1'~detected. } + { + Use: \\ + \ \ \token_to_str:N \usepackage [ version-1-compatibility ] + \iow_char:N \{ siunitx \token_to_str:N \iow_char:N \} \\ + in~the~preamble~to~load~the~appropriate~code. + } +% \end{macrocode} +% +%\subsection{Design-level macros} +% +%\begin{macro}{\DeclareBinaryPrefix} +%\begin{macro}{\DeclareSIPostPower} +%\begin{macro}{\DeclareSIPrefix} +%\begin{macro}{\DeclareSIPrePower} +%\begin{macro}{\DeclareSIQualifier} +%\begin{macro}{\DeclareSIUnit} +%\begin{macro}{\DeclareSIUnitWithOptions} +% The macros for creating units and so on are in design name space. +% Basically, a set of shuffles for arguments. +% \begin{macrocode} +\NewDocumentCommand \DeclareBinaryPrefix { m m m } { + \@@_declare_prefix:Nnnn #1 {#2} { 2 } {#3} +} +\NewDocumentCommand \DeclareSIPostPower { m m } { + \@@_declare_power_after:Nn #1 {#2} +} +\NewDocumentCommand \DeclareSIPrefix { m m m } { + \@@_declare_prefix:Nnnn #1 {#2} { 10 } {#3} +} +\NewDocumentCommand \DeclareSIPrePower { m m } { + \@@_declare_power_before:Nn #1 {#2} +} +\NewDocumentCommand \DeclareSIQualifier { m m } { + \@@_declare_qualifier:Nn #1 {#2} +} +\NewDocumentCommand \DeclareSIUnit { O { } m m } { + \@@_declare_unit:Nnn #2 {#3} {#1} +} +\NewDocumentCommand \DeclareSIUnitWithOptions { m m m } { + \@@_declare_unit:Nnn #1 {#2} {#3} +} +% \end{macrocode} +%\end{macro} +%\end{macro} +%\end{macro} +%\end{macro} +%\end{macro} +%\end{macro} +%\end{macro} +% +% None of this should be done after the preamble. +% \begin{macrocode} +\@onlypreamble \DeclareBinaryPrefix +\@onlypreamble \DeclareSIPostPower +\@onlypreamble \DeclareSIPrefix +\@onlypreamble \DeclareSIPrePower +\@onlypreamble \DeclareSIQualifier +\@onlypreamble \DeclareSIUnit +\@onlypreamble \DeclareSIUnitWithOptions +% \end{macrocode} +% +%\begin{macro}{\SendSettingsToPgf} +% A settings transfer function. +% \begin{macrocode} +\cs_new_protected:Npn \SendSettingsToPgf { \@@_pgf_link: } +% \end{macrocode} +%\end{macro} +% +%\subsection{Document macros} +% +% The user document macros are all collected together here for ease. +% +%\begin{macro}{\ang} +% The \cs{ang} function does very little beyond setting the local +% keys and passing on the input. +% \begin{macrocode} +\NewDocumentCommand \ang { o > { \SplitArgument { 2 } { ; } } m } { + \group_begin: + \IfNoValueF {#1} + { \keys_set:nn { siunitx } {#1} } + \@@_angle_output:nnn #2 + \group_end: +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\num} +% The \cs{num} macro is quite simple: read the number, check it is +% correct then print it. +% \begin{macrocode} +\NewDocumentCommand \num { o m } { + \leavevmode + \group_begin: + \bool_set_false:N \l_@@_font_set_bool + \IfNoValueF {#1} + { \keys_set:nn { siunitx } {#1} } + \@@_number_output:n {#2} + \group_end: +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\numlist} +% Lists of numbers are trivially easy to work with. +% \begin{macrocode} +\NewDocumentCommand \numlist { o > { \SplitList { ; } } m } { + \leavevmode + \group_begin: + \bool_set_false:N \l_@@_font_set_bool + \IfNoValueF {#1} + { \keys_set:nn { siunitx } {#1} } + \@@_list_numbers:n {#2} + \group_end: +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\numrange} +% A very simple approach is taken here: this is not intended for +% anything complicated. +% \begin{macrocode} +\NewDocumentCommand \numrange { o m m } { + \leavevmode + \group_begin: + \bool_set_false:N \l_@@_font_set_bool + \IfNoValueF {#1} + { \keys_set:nn { siunitx } {#1} } + \@@_range_numbers:nn {#2} {#3} + \group_end: +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{ +% \SIlist , +% \SIrange +%} +% Lists and range of values are handled in a very similar way. +% Everything is kept relatively simple, and so there is not too much +% complexity. In theory the two could be combined together, but +% the differences between the two make this less desirable. +% \begin{macrocode} +\NewDocumentCommand \SIlist { o > { \SplitList { ; } } m m } { + \leavevmode + \group_begin: + \bool_set_false:N \l_@@_font_set_bool + \IfNoValueTF {#1} + { \@@_list_units:nnn {#2} {#3} { } } + { + \keys_set:nn { siunitx } {#1} + \@@_list_units:nnn {#2} {#3} {#1} + } + \group_end: +} +\NewDocumentCommand \SIrange { o m m m } { + \leavevmode + \group_begin: + \bool_set_false:N \l_@@_font_set_bool + \IfNoValueTF {#1} + { \@@_range_unit:nnnn {#4} { } {#2} {#3} } + { + \keys_set:nn { siunitx } {#1} + \@@_range_unit:nnnn {#4} {#1} {#2} {#3} + } + \group_end: +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\SI} +% The main \cs{SI} function follows the same pattern as the previous +% ones. +% \begin{macrocode} +\NewDocumentCommand \SI { o m o m } { + \leavevmode + \group_begin: + \bool_set_false:N \l_@@_font_set_bool + \IfNoValueTF {#1} + { \@@_combined:nnnn { } {#2} {#3} {#4} } + { + \keys_set:nn { siunitx } {#1} + \@@_combined:nnnn {#1} {#2} {#3} {#4} + } + \group_end: +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\sisetup} +% The set up macro simply moves to the correct path and executes +% whatever has been passed. +% \begin{macrocode} +\NewDocumentCommand \sisetup { m } { + \keys_set:nn { siunitx } {#1} +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\tablenum} +% A variation on the \cs{num} macro that will retain alignment within +% \cs{multicolumn} and \cs{multirow} situations. The slightly odd code +% for the non-parsed case is needed to reinsert the appropriate tokens +% after \enquote{collection}. +% \begin{macrocode} +\NewDocumentCommand \tablenum { o m } { + \leavevmode + \group_begin: + \bool_set_false:N \l_@@_font_set_bool + \IfNoValueF {#1} + { \keys_set:nn { siunitx } {#1} } + \bool_if:NTF \l_@@_number_parse_bool + { + \tl_set:Nn \l_@@_table_collect_tl {#2} + \bool_set_false:N \l_@@_table_collect_pre_bool + \@@_table_print_S: + } + { \@@_table_print_S_direct: #2 \@@_table_print: } + \group_end: +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\si} +% The \cs{si} macro needs to pass options through to the internal +% function as well as setting them here. This is used so that options +% set for a unit can be overridden on a one-off basis. +% \begin{macrocode} +\NewDocumentCommand \si { o m } { + \leavevmode + \group_begin: + \bool_set_false:N \l_@@_font_set_bool + \IfNoValueTF {#1} + { \@@_unit_output:nn {#2} { } } + { + \keys_set:nn { siunitx } {#1} + \@@_unit_output:nn {#2} {#1} + } + \group_end: +} +% \end{macrocode} +%\end{macro} +% +%\subsection{Precautions for section headings} +% +% There are two issues to be handled for section headings, \emph{etc}. +% First, within the \cs{addcontentline} macro the various unit functions +% need to be \cs{protected}. Secondly, there is a need to worry about +% \pkg{hyperref}, and ensure that everything works cleanly and with +% no unnecessary warnings. +% +% \begin{macro}{\@@_contents_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_siunitx_unit_symbolic_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_siunitx_unit_symbolic_seq + { \@@_unit_print_literal_aux:N ##1 } + \cs_if_exist:NT \FB@fg + { \cs_set_eq:NN \fg \FB@fg } + \msg_redirect_name:nnn { xparse } { redefine-command } { none } + \cs_set_eq:NN \num \numInBookmark + \cs_set_eq:NN \numrange \numrangeInBookmark + \cs_set_eq:NN \si \siInBookmark + \cs_set_eq:NN \SI \SIInBookmark + \cs_set_eq:NN \SIrange \SIrangeInBookmark + \cs_set_eq:NN \si \siInBookmark + \cs_set_eq:NN \highlight \use_ii:nn + \cs_set_eq:NN \@@_textsuperscript:n \use:n + \cs_set:Npn \SIUnitSymbolAngstrom { \AA } + \cs_set:Npn \SIUnitSymbolArcminute { ' } + \cs_set:Npn \SIUnitSymbolArcsecond { '' } + \cs_set:Npn \SIUnitSymbolCelsius { \textcelsius } + \cs_set:Npn \SIUnitSymbolDegree { \textdegree } + \cs_set:Npn \SIUnitSymbolMicro { \textmu } + \cs_set:Npn \SIUnitSymbolOhm { [ohm] } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro} +% { +% \numInBookmark , +% \numrangeInBookmark , +% \SIlistInBookmark , +% \SIrangeInBookmark , +% \SIInBookmark , +% \siInBookmark +% } +% To keep things fast, expandable versions of the document commands +% are created only once. These are then used if necessary to remove +% and re-order arguments in an expandable fashion. +% \begin{macrocode} +\DeclareExpandableDocumentCommand \numInBookmark { o m } {#2} +\DeclareExpandableDocumentCommand \numrangeInBookmark { o m m } + { #2 \l_@@_range_phrase_tl #3 } +\DeclareExpandableDocumentCommand \SIInBookmark { o m o m } + { \IfNoValueF {#3} {#3} #2 ~ #4 } +\DeclareExpandableDocumentCommand \SIlistInBookmark + { o m m } { \@@_bookmark_SIlist_map:nn {#1} {#2} } +\DeclareExpandableDocumentCommand \SIrangeInBookmark + { o m m m } { #2 ~ #4 \l_@@_range_phrase_tl #3 ~ #4 } +\DeclareExpandableDocumentCommand \siInBookmark { o m } {#2} +% \end{macrocode} +% \end{macro} +% +%\begin{macro}{\@@_bookmark_SIlist_map:nn} +%\begin{macro}{\@@_bookmark_SIlist_map_aux:nw} +% An expandable mapping to replace the list separator in the +% input by appropriate output version. +% \begin{macrocode} +\cs_new:Npn \@@_bookmark_SIlist_map:nn #1#2 { + \@@_bookmark_SIlist_map_aux:nw {#2} #1 ; \q_recursion_tail ; + \q_recursion_tail ; \q_recursion_stop +} +\cs_new:Npn \@@_bookmark_SIlist_map_aux:nw #1#2 ; #3 ; #4 { + #2 ~ #1 + \quark_if_recursion_tail_stop:n {#3} + \quark_if_recursion_tail_stop_do:nn {#4} + { + \l_@@_list_separator_final_tl + #3 ~ #1 + } + \l_@@_list_separator_tl + \@@_bookmark_SIlist_map_aux:nw {#1} #3 ; #4 +} +% \end{macrocode} +%\end{macro} +%\end{macro} +% +% A short check to get things working. +% \begin{macrocode} +\AtBeginDocument { + \@ifpackageloaded { hyperref } + { \pdfstringdefDisableCommands { \@@_contents_bookmarks: } } + { } +} +% \end{macrocode} +% +%\subsection{Physical units} +% +%\begin{macro}{\kilogram} +%\begin{macro}{\metre} +%\begin{macro}{\meter} +%\begin{macro}{\mole} +%\begin{macro}{\kelvin} +%\begin{macro}{\candela} +%\begin{macro}{\second} +%\begin{macro}{\ampere} +% The basic SI units are always defined, including both variants for +% metre. +% \begin{macrocode} +\DeclareSIUnit \kilogram { \kilo \gram } +\DeclareSIUnit \metre { m } +\DeclareSIUnit \meter { \metre } +\DeclareSIUnit \mole { mol } +\DeclareSIUnit \second { s } +\DeclareSIUnit \ampere { A } +\DeclareSIUnit \kelvin { K } +\DeclareSIUnit \candela { cd } +% \end{macrocode} +%\end{macro} +%\end{macro} +%\end{macro} +%\end{macro} +%\end{macro} +%\end{macro} +%\end{macro} +%\end{macro} +% +%\begin{macro}{\gram} +% The gram is an odd unit as it is needed for the base unit kilogram. +% \begin{macrocode} +\DeclareSIUnit \gram { g } +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\yocto} +%\begin{macro}{\zepto} +%\begin{macro}{\atto} +%\begin{macro}{\femto} +%\begin{macro}{\pico} +%\begin{macro}{\nano} +%\begin{macro}{\micro} +%\begin{macro}{\milli} +%\begin{macro}{\centi} +%\begin{macro}{\deci} +% The various SI multiple prefixes are defined here: first the small +% ones. +% \begin{macrocode} +\DeclareSIPrefix \yocto { y } { -24 } +\DeclareSIPrefix \zepto { z } { -21 } +\DeclareSIPrefix \atto { a } { -18 } +\DeclareSIPrefix \femto { f } { -15 } +\DeclareSIPrefix \pico { p } { -12 } +\DeclareSIPrefix \nano { n } { -9 } +\DeclareSIPrefix \micro { \SIUnitSymbolMicro } { -6 } +\DeclareSIPrefix \milli { m } { -3 } +\DeclareSIPrefix \centi { c } { -2 } +\DeclareSIPrefix \deci { d } { -1 } +% \end{macrocode} +%\end{macro} +%\end{macro} +%\end{macro} +%\end{macro} +%\end{macro} +%\end{macro} +%\end{macro} +%\end{macro} +%\end{macro} +%\end{macro} +%\begin{macro}{\deca} +%\begin{macro}{\deka} +%\begin{macro}{\hecto} +%\begin{macro}{\kilo} +%\begin{macro}{\mega} +%\begin{macro}{\giga} +%\begin{macro}{\tera} +%\begin{macro}{\peta} +%\begin{macro}{\exa} +%\begin{macro}{\zetta} +%\begin{macro}{\yotta} +% Now the large ones. +% \begin{macrocode} +\DeclareSIPrefix \deca { da } { 1 } +\DeclareSIPrefix \deka { da } { 1 } +\DeclareSIPrefix \hecto { h } { 2 } +\DeclareSIPrefix \kilo { k } { 3 } +\DeclareSIPrefix \mega { M } { 6 } +\DeclareSIPrefix \giga { G } { 9 } +\DeclareSIPrefix \tera { T } { 12 } +\DeclareSIPrefix \peta { P } { 15 } +\DeclareSIPrefix \exa { E } { 18 } +\DeclareSIPrefix \zetta { Z } { 21 } +\DeclareSIPrefix \yotta { Y } { 24 } +% \end{macrocode} +%\end{macro} +%\end{macro} +%\end{macro} +%\end{macro} +%\end{macro} +%\end{macro} +%\end{macro} +%\end{macro} +%\end{macro} +%\end{macro} +%\end{macro} +% +%\begin{macro}{\becquerel} +%\begin{macro}{\celsius} +%\begin{macro}{\degreeCelsius} +%\begin{macro}{\coulomb} +%\begin{macro}{\farad} +%\begin{macro}{\gray} +%\begin{macro}{\hertz} +%\begin{macro}{\henry} +%\begin{macro}{\joule} +%\begin{macro}{\katal} +%\begin{macro}{\lumen} +%\begin{macro}{\lux} +% A number of derived units with defined names and symbols. +% \begin{macrocode} +\DeclareSIUnit \becquerel { Bq } +\DeclareSIUnit \celsius { \SIUnitSymbolCelsius } +\DeclareSIUnit \degreeCelsius { \SIUnitSymbolCelsius } +\DeclareSIUnit \coulomb { C } +\DeclareSIUnit \farad { F } +\DeclareSIUnit \gray { Gy } +\DeclareSIUnit \hertz { Hz } +\DeclareSIUnit \henry { H } +\DeclareSIUnit \joule { J } +\DeclareSIUnit \katal { kat } +\DeclareSIUnit \lumen { lm } +\DeclareSIUnit \lux { lx } +% \end{macrocode} +%\end{macro} +%\end{macro} +%\end{macro} +%\end{macro} +%\end{macro} +%\end{macro} +%\end{macro} +%\end{macro} +%\end{macro} +%\end{macro} +%\end{macro} +%\end{macro} +%\begin{macro}{\newton} +%\begin{macro}{\ohm} +%\begin{macro}{\pascal} +%\begin{macro}{\radian} +%\begin{macro}{\siemens} +%\begin{macro}{\sievert} +%\begin{macro}{\steradian} +%\begin{macro}{\tesla} +%\begin{macro}{\volt} +%\begin{macro}{\watt} +%\begin{macro}{\weber} +% More units. +% \begin{macrocode} +\DeclareSIUnit \newton { N } +\DeclareSIUnit \ohm { \SIUnitSymbolOhm } +\DeclareSIUnit \pascal { Pa } +\DeclareSIUnit \radian { rad } +\DeclareSIUnit \siemens { S } +\DeclareSIUnit \sievert { Sv } +\DeclareSIUnit \steradian { sr } +\DeclareSIUnit \tesla { T } +\DeclareSIUnit \volt { V } +\DeclareSIUnit \watt { W } +\DeclareSIUnit \weber { Wb } +% \end{macrocode} +%\end{macro} +%\end{macro} +%\end{macro} +%\end{macro} +%\end{macro} +%\end{macro} +%\end{macro} +%\end{macro} +%\end{macro} +%\end{macro} +%\end{macro} +% +%\begin{macro}{\arcminute} +%\begin{macro}{\arcsecond} +%\begin{macro}{\day} +%\begin{macro}{\degree} +%\begin{macro}{\hectare} +%\begin{macro}{\hour} +%\begin{macro}{\litre} +%\begin{macro}{\liter} +%\begin{macro}{\minute} +%\begin{macro}{\percent} +%\begin{macro}{\tonne} +% Non-SI, but accepted for general use. +% \begin{macrocode} +\DeclareSIUnit [ number-unit-product = ] \arcmin { \arcminute } +\DeclareSIUnit [ number-unit-product = ] + \arcminute { \SIUnitSymbolArcminute } +\DeclareSIUnit [ number-unit-product = ] + \arcsecond { \SIUnitSymbolArcsecond } +\DeclareSIUnit \day { d } +\DeclareSIUnit[ number-unit-product = ] \degree { \SIUnitSymbolDegree } +\DeclareSIUnit \hectare { ha } +\DeclareSIUnit \hour { h } +\DeclareSIUnit \litre { l } +\DeclareSIUnit \liter { L } +\DeclareSIUnit \minute { min } +\DeclareSIUnit \percent { \char 37 } +\DeclareSIUnit \tonne { t } +% \end{macrocode} +%\end{macro} +%\end{macro} +%\end{macro} +%\end{macro} +%\end{macro} +%\end{macro} +%\end{macro} +%\end{macro} +%\end{macro} +%\end{macro} +%\end{macro} +% +%\begin{macro}{\astronomicalunit} +%\begin{macro}{\atomicmassunit} +%\begin{macro}{\electronvolt} +%\begin{macro}{\dalton} +% A few units based on physical measurements exist. +% \begin{macrocode} +\DeclareSIUnit \astronomicalunit { au } +\DeclareSIUnit \atomicmassunit { u } +\DeclareSIUnit \electronvolt { eV } +\DeclareSIUnit \dalton { Da } +% \end{macrocode} +%\end{macro} +%\end{macro} +%\end{macro} +%\end{macro} +%\begin{macro}{\clight} +%\begin{macro}{\electronmass} +%\begin{macro}{\planckbar} +% A set of \enquote{natural units}. +% \begin{macrocode} +\group_begin: +\cs_set_eq:NN \endgroup \group_end: +\char_set_catcode_math_subscript:N \_ +\use:n + { + \endgroup + \DeclareSIUnit \clight { \text { \ensuremath { c _ { 0 } } } } + \DeclareSIUnit \electronmass + { \text { \ensuremath { m _ { \textup { e } } } } } + } +\DeclareSIUnit \planckbar { \text { \ensuremath { \hbar } } } +% \end{macrocode} +%\end{macro} +%\end{macro} +%\end{macro} +%\begin{macro}{\elementarycharge} +%\begin{macro}{\bohr} +%\begin{macro}{\hartree} +% A set of \enquote{atomic units}. +% \begin{macrocode} +\DeclareSIUnit \elementarycharge { \text { \ensuremath { e } } } +\group_begin: +\cs_set_eq:NN \endgroup \group_end: +\char_set_catcode_math_subscript:N \_ +\use:n + { + \endgroup + \DeclareSIUnit \bohr { \text { \ensuremath { a _ { 0 } } } } + \DeclareSIUnit \hartree + { \text { \ensuremath { E _ { \textup { h } } } } } + } +% \end{macrocode} +%\end{macro} +%\end{macro} +%\end{macro} +% +%\begin{macro}{\angstrom} +%\begin{macro}{\bar} +%\begin{macro}{\barn} +%\begin{macro}{\bel} +%\begin{macro}{\decibel} +%\begin{macro}{\knot} +%\begin{macro}{\mmHg} +%\begin{macro}{\nauticalmile} +%\begin{macro}{\neper} +% There are then some day-to-day units which are accepted for use +% with SI, but are not part of the official specification. +% \begin{macrocode} +\DeclareSIUnit \angstrom { \SIUnitSymbolAngstrom } +\DeclareSIUnit \bar { bar } +\DeclareSIUnit \barn { b } +\DeclareSIUnit \bel { B } +\DeclareSIUnit \decibel { \deci \bel } +\DeclareSIUnit \knot { kn } +\DeclareSIUnit \mmHg { mmHg } +\DeclareSIUnit \nauticalmile { M } +\DeclareSIUnit \neper { Np } +% \end{macrocode} +%\end{macro} +%\end{macro} +%\end{macro} +%\end{macro} +%\end{macro} +%\end{macro} +%\end{macro} +%\end{macro} +%\end{macro} +% +%\begin{macro}{\square} +%\begin{macro}{\squared} +%\begin{macro}{\cubic} +%\begin{macro}{\cubed} +% The basic powers are also defined. +% \begin{macrocode} +\DeclareSIPrePower \square { 2 } +\DeclareSIPostPower \squared { 2 } +\DeclareSIPrePower \cubic { 3 } +\DeclareSIPostPower \cubed { 3 } +% \end{macrocode} +%\end{macro} +%\end{macro} +%\end{macro} +%\end{macro} +% +%\subsection{Strict application of the rules} +% +%\begin{macro}{\@@_strict_option:n} +%\begin{macro}{\@@_strict_option_aux:n} +% When sticking to the rules closely, a few options are not available. +% \begin{macrocode} +\keys_define:nn { siunitx } { + strict .code:n = + { + \keys_set:nn { siunitx } + { + bracket-numbers = true, + detect-family = false, + detect-mode = false, + detect-shape = false, + detect-weight = false, + multi-part-units = brackets, + parse-numbers = true, + parse-units = true, + product-units = repeat + } + \@@_strict_option:n + { + bracket-numbers , + detect-family , + detect-italic , + detect-mode , + detect-shape , + detect-weight , + multi-part-units , + parse-numbers , + parse-units , + product-units + } + \keys_define:nn { siunitx } + { + per-mode / repeated-symbol .code:n = + { + \msg_warning:nnx { siunitx } { option-not-available } + { per-mode~=~repeated-symbol } + } + } + } +} +\@@_option_deactivate:n { strict } +\cs_new_protected:Npn \@@_strict_option:n #1 { + \clist_map_function:nN {#1} \@@_strict_option_aux:n +} +\cs_new_protected:Npn \@@_strict_option_aux:n #1 { + \keys_define:nn { siunitx } + { #1 .code:n = + { \msg_warning:nnx { siunitx } { option-not-available } {#1} } + } +} +% \end{macrocode} +%\end{macro} +%\end{macro} +% +%\subsection{Locales} +% +% The basics for defining locales are easy: these are just meta keys. +% The US locale is simply an alias for the UK one, which is the default. +% \begin{macrocode} +\keys_define:nn { siunitx } { + locale .choice:, + locale / + DE .meta:n = + { + exponent-product = \ensuremath { \cdot } , + inter-unit-product = \, , + output-decimal-marker = { , } + }, + locale / + FR .meta:n = + { + exponent-product = \ensuremath { \times } , + inter-unit-product = \, , + output-decimal-marker = { , } + }, + locale / + UK .meta:n = + { + exponent-product = \ensuremath { \times } , + inter-unit-product = \, , + output-decimal-marker = . + }, + locale / + US .meta:n = { locale = UK }, + locale / + USA .meta:n = { locale = UK }, + locale / + ZA .meta:n = + { + exponent-product = \ensuremath { \times } , + inter-unit-product = \ensuremath { \cdot } , + output-decimal-marker = { , } + }, +} +% \end{macrocode} +% +%\subsection{Localisation} +% +% Localisation makes use of the \pkg{translator} package. This only +% happens if it is available, and is transparent to the user. +% \begin{macrocode} +\file_if_exist:nT { translator.sty } + { + \RequirePackage { translator } + \usedictionary { translator-basic-dictionary } + \providetranslation [ to = English ] + { to~(numerical~range) } { to } + \providetranslation [ to = French ] + { to~(numerical~range) } { \`a } + \providetranslation [ to = German ] + { to~(numerical~range) } { bis } + \providetranslation [ to = Spanish ] + { to~(numerical~range) } { a } + \sisetup + { + list-final-separator = { ~ \translate { and } ~ }, + list-pair-separator = { ~ \translate { and } ~ }, + range-phrase = { ~ \translate { to~(numerical~range) } ~ } + } + } +% \end{macrocode} +% +% \subsection{Loading additional configurations} +% +% \begin{variable}{\c_@@_configuration_ext_tl} +% Logical mark-up for the file extension. +% \begin{macrocode} +\tl_const:Nn \c_@@_configuration_ext_tl { cfg } +% \end{macrocode} +% \end{variable} +% +% \begin{macro}{\@@_load_abbreviations:} +% \begin{macro}{\@@_load_binary:} +% Loading abbreviations is on by default, which therefore requires a bit +% of juggling. The idea here is that the abbreviations will be loaded unless +% specifically turned off. This can occur anywhere in the preamble. +% \begin{macrocode} +\keys_define:nn { siunitx } + { + abbreviations .choice:, + abbreviations / + true .code:n = { \@@_load_abbreviations: }, + abbreviations / + false .code:n = + { \cs_set_eq:NN \@@_load_abbreviations: \prg_do_nothing: } , + abbreviations .default:n = true , + binary-units .choice:, + binary-units / + true .code:n = { \AtBeginDocument { \@@_load_binary: } }, + binary-units / + false .code:n = + { \cs_set_eq:NN \@@_load_binary: \prg_do_nothing: } , + binary-units .default:n = true + } +\cs_new_protected:Npn \@@_load_abbreviations: + { + \@onefilewithoptions { siunitx-abbreviations } [ ] [ ] + \c_@@_configuration_ext_tl + } +\cs_new_protected:Npn \@@_load_binary: + { + \@onefilewithoptions { siunitx-binary } [ ] [ ] + \c_@@_configuration_ext_tl + } +\AtBeginDocument { \@@_load_abbreviations: } +\@@_option_deactivate:n { abbreviations , binary } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% The version 1 options are not loaded as standard. +% \begin{macrocode} +\keys_define:nn { siunitx } + { + version-1-compatibility .choice: , + version-1-compatibility / + true .code:n = + { + \@onefilewithoptions { siunitx-version-1 } [ ] [ ] + \c_@@_configuration_ext_tl + }, + version-1-compatibility / + false .code:n = { } , + version-1-compatibility .default:n = true + } +\@@_option_deactivate:n { version-1-compatibility } +% \end{macrocode} +% +% Dealing with the old \opt{load-configurations} option is pretty easy, as +% only one choice is important. +% \begin{macrocode} +\keys_define:nn { siunitx } { + load-configurations .code:n = + { + \clist_if_in:nnT {#1} { version-1 } + { + \@onefilewithoptions { siunitx-version-1 } [ ] [ ] + \c_@@_configuration_ext_tl + } + } +} +\@@_option_deactivate:n { load-configurations } +% \end{macrocode} +% +% Load any local configuration file. +% \begin{macrocode} +\file_if_exist:nT { siunitx . \c_@@_configuration_ext_tl } + { + \@onefilewithoptions { siunitx } [ ] [ ] + \c_@@_configuration_ext_tl + } +% \end{macrocode} +% +% Finally apply the settings given at load time. +% \begin{macrocode} +\ProcessKeysOptions { siunitx } +% \end{macrocode} +% +% Creating document commands has to happen here so it is after any load-time +% changes to the units available. +% \begin{macrocode} +\AtBeginDocument { + \bool_if:NTF \l_@@_create_free_bool + { \@@_unit_create_functions: } + { \@@_unit_create_empty_functions: } +} +% \end{macrocode} +% +% \begin{macrocode} +% +% \end{macrocode} +% +%\subsection{Support for version one} +% +% \begin{macrocode} +%<*version-1> +% \end{macrocode} +% +% \begin{macrocode} +\ProvidesExplFile {siunitx-version-1.cfg} {2017/11/26} {2.7k} + {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} {2017/11/26} {2.7k} + {siunitx: Abbreviated units} +% \end{macrocode} +% +% The abbreviation file contains a number of short (mainly two or +% three letter) versions of the usual long names. They are divided up +% into related groups, mainly to avoid an overly long list in one +% place. +% +% \begin{macro}{\A, \pA, \nA, \uA, \mA, \kA} +% Currents. +% \begin{macrocode} +\DeclareSIUnit \A { \ampere } +\DeclareSIUnit \pA { \pico \ampere } +\DeclareSIUnit \nA { \nano \ampere } +\DeclareSIUnit \uA { \micro \ampere } +\DeclareSIUnit \mA { \milli \ampere } +\DeclareSIUnit \kA { \kilo \ampere } +% \end{macrocode} +% \end{macro} +% \begin{macro}{\Hz, \mHz, \kHz, \MHz, \GHz, \THz} +% Then frequencies. +% \begin{macrocode} +\DeclareSIUnit \Hz { \hertz } +\DeclareSIUnit \mHz { \milli \hertz } +\DeclareSIUnit \kHz { \kilo \hertz } +\DeclareSIUnit \MHz { \mega \hertz } +\DeclareSIUnit \GHz { \giga \hertz } +\DeclareSIUnit \THz { \tera \hertz } +% \end{macrocode} +% \end{macro} +% \begin{macro}{\mol, \fmol, \pmol, \nmol, \umol, \mmol, \kmol} +% Amounts of substance (moles). +% \begin{macrocode} +\DeclareSIUnit \mol { \mole } +\DeclareSIUnit \fmol { \femto \mole } +\DeclareSIUnit \pmol { \pico \mole } +\DeclareSIUnit \nmol { \nano \mole } +\DeclareSIUnit \umol { \micro \mole } +\DeclareSIUnit \mmol { \milli \mole } +\DeclareSIUnit \kmol { \kilo \mole } +% \end{macrocode} +% \end{macro} +% \begin{macro}{\V, \pV, \nV, \uV, \mV, \kV} +% Potentials. +% \begin{macrocode} +\DeclareSIUnit \V { \volt } +\DeclareSIUnit \pV { \pico \volt } +\DeclareSIUnit \nV { \nano \volt } +\DeclareSIUnit \uV { \micro \volt } +\DeclareSIUnit \mV { \milli \volt } +\DeclareSIUnit \kV { \kilo \volt } +% \end{macrocode} +% \end{macro} +% \begin{macro}{\hl, \l, \ml, \ul, \hL, \L, \mL, \uL} +% Volumes. +% \begin{macrocode} +\DeclareSIUnit \hl { \hecto \litre } +\DeclareSIUnit \l { \litre } +\DeclareSIUnit \ml { \milli \litre } +\DeclareSIUnit \ul { \micro \litre } +\DeclareSIUnit \hL { \hecto \liter } +\DeclareSIUnit \L { \liter } +\DeclareSIUnit \mL { \milli \liter } +\DeclareSIUnit \uL { \micro \liter } +% \end{macrocode} +% \end{macro} +% \begin{macro}{\fg, \pg, \ng, \ug, \mg, \g, \kg, \amu} +% Masses. +% \begin{macrocode} +\DeclareSIUnit \fg { \femto \gram } +\DeclareSIUnit \pg { \pico \gram } +\DeclareSIUnit \ng { \nano \gram } +\DeclareSIUnit \ug { \micro \gram } +\DeclareSIUnit \mg { \milli \gram } +\DeclareSIUnit \g { \gram } +\DeclareSIUnit \kg { \kilo \gram } +\DeclareSIUnit \amu { \atomicmassunit } +% \end{macrocode} +% \end{macro} +% \begin{macro} +% {\W, \uW, \mW, \kW, \MW, \GW, \kJ, \J, \mJ, \uJ, \eV, \meV, \keV, \MeV, \GeV, \TeV, \kWh} +% Energies. +% \begin{macrocode} +\DeclareSIUnit \W { \watt } +\DeclareSIUnit \uW { \micro \watt } +\DeclareSIUnit \mW { \milli \watt } +\DeclareSIUnit \kW { \kilo \watt } +\DeclareSIUnit \MW { \mega \watt } +\DeclareSIUnit \GW { \giga \watt } +\DeclareSIUnit \J { \joule } +\DeclareSIUnit \uJ { \micro \joule } +\DeclareSIUnit \mJ { \milli \joule } +\DeclareSIUnit \kJ { \kilo \joule } +\DeclareSIUnit \eV { \electronvolt } +\DeclareSIUnit \meV { \milli \electronvolt } +\DeclareSIUnit \keV { \kilo \electronvolt } +\DeclareSIUnit \MeV { \mega \electronvolt } +\DeclareSIUnit \GeV { \giga \electronvolt } +\DeclareSIUnit \TeV { \tera \electronvolt } +\DeclareSIUnit [ inter-unit-product = ] \kWh { \kilo \watt \hour } +% \end{macrocode} +% \end{macro} +% \begin{macro}{\m, \pm, \nm, \um, \mm, \cm, \dm, \km} +% Lengths. +% \begin{macrocode} +\DeclareSIUnit \m { \metre } +\DeclareSIUnit \pm { \pico \metre } +\DeclareSIUnit \nm { \nano \metre } +\DeclareSIUnit \um { \micro \metre } +\DeclareSIUnit \mm { \milli \metre } +\DeclareSIUnit \cm { \centi \metre } +\DeclareSIUnit \dm { \deci \metre } +\DeclareSIUnit \km { \kilo \metre } +% \end{macrocode} +% \end{macro} +% \begin{macro}{\K} +% Temperatures. +% \begin{macrocode} +\DeclareSIUnit \K { \kelvin } +% \end{macrocode} +% \end{macro} +% \begin{macro}{\dB} +% \begin{macrocode} +\DeclareSIUnit \dB { \deci \bel } +% \end{macrocode} +% \end{macro} +% \begin{macro}{\F, \fF, \pF} +% \begin{macrocode} +\DeclareSIUnit \F { \farad } +\DeclareSIUnit \fF { \femto \farad } +\DeclareSIUnit \pF { \pico \farad } +% \end{macrocode} +% \end{macro} +% \begin{macro}{\N, \mN, \kN, \MN} +% Forces. +% \begin{macrocode} +\DeclareSIUnit \N { \newton } +\DeclareSIUnit \mN { \milli \newton } +\DeclareSIUnit \kN { \kilo \newton } +\DeclareSIUnit \MN { \mega \newton } +% \end{macrocode} +% \end{macro} +% \begin{macro}{\Pa, \kPa, \MPa, \GPa} +% Pressures. +% \begin{macrocode} +\DeclareSIUnit \Pa { \pascal } +\DeclareSIUnit \kPa { \kilo \pascal } +\DeclareSIUnit \MPa { \mega \pascal } +\DeclareSIUnit \GPa { \giga \pascal } +% \end{macrocode} +% \end{macro} +% \begin{macro}{\mohm, \kohm, \Mohm} +% Resistances. +% \begin{macrocode} +\DeclareSIUnit \mohm { \milli \ohm } +\DeclareSIUnit \kohm { \kilo \ohm } +\DeclareSIUnit \Mohm { \mega \ohm } +% \end{macrocode} +% \end{macro} +% \begin{macro}{\s, \as, \fs, \ps, \ns, \us, \ms} +% Finally, times. +% \begin{macrocode} +\DeclareSIUnit \s { \second } +\DeclareSIUnit \as { \atto \second } +\DeclareSIUnit \fs { \femto \second } +\DeclareSIUnit \ps { \pico \second } +\DeclareSIUnit \ns { \nano \second } +\DeclareSIUnit \us { \micro \second } +\DeclareSIUnit \ms { \milli \second } +% \end{macrocode} +% \end{macro} +% +% \begin{macrocode} +% +% \end{macrocode} +% +% \subsection{Binary units} +% +% \begin{macrocode} +%<*binary> +% \end{macrocode} +% +% \begin{macrocode} +\ProvidesExplFile {siunitx-binary.cfg} {2017/11/26} {2.7k} + {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/measurement-units/}. +% +% \bibitem{NIST} +% \emph{International System of Units from NIST}, +% \url{http://physics.nist.gov/cuu/Units/index.html}. +% +% \bibitem{SI:2.1} +% \emph{SI base units}, +% \url{http://www.bipm.org/en/publications/si-brochure/section2-1.html}. +% +% \bibitem{SI:2.2.2} +% \emph{Units with special names and symbols; units that +% incorporate special names and symbols}, +% \url{http://www.bipm.org/en/publications/si-brochure/section2-2-2.html}. +% +% \bibitem{SI:3.1} +% \emph{SI Prefixes}, +% \url{http://www.bipm.org/en/publications/si-brochure/chapter3.html}. +% +% \bibitem{SI:4.1.T6} +% \emph{Non-SI units accepted for use with the International +% System of Units}, +% \url{http://www.bipm.org/en/publications/si-brochure/table6.html}. +% +% \bibitem{SI:4.1.T7} +% \emph{Non-SI units whose values in SI units must be obtained +% experimentally}, +% \url{http://www.bipm.org/en/publications/si-brochure/table7.html}. +% +% \bibitem{SI:4.1.T8} +% \emph{Other non-SI units}, +% \url{http://www.bipm.org/en/publications/si-brochure/table8.html}. +% +% \bibitem{SI:5.3.3} +% \emph{Formatting the value of a quantity}, +% \url{http://www.bipm.org/en/publications/si-brochure/section5-3-3.html}. +% +% \end{thebibliography} +% +% \PrintChanges +% +% \newpage +% +% \PrintIndex diff --git a/macros/latex/contrib/siunitx/siunitx.pdf b/macros/latex/contrib/siunitx/siunitx.pdf new file mode 100644 index 0000000000..6bd27ee216 Binary files /dev/null and b/macros/latex/contrib/siunitx/siunitx.pdf differ -- cgit v1.2.3