diff options
author | Karl Berry <karl@freefriends.org> | 2018-04-29 22:36:26 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2018-04-29 22:36:26 +0000 |
commit | f3b8211e18e1d53d0aa1e0412c0765e1178bb509 (patch) | |
tree | ea7ab07bfac5f48e64567a8df27b91addd722637 /Master/texmf-dist/source/latex/siunitx | |
parent | a824ebbc1915d27c9e93507a0729350f7507320f (diff) |
siunitx (27apr18)
git-svn-id: svn://tug.org/texlive/trunk@47489 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/source/latex/siunitx')
-rw-r--r-- | Master/texmf-dist/source/latex/siunitx/siunitx-angle.dtx | 84 | ||||
-rw-r--r-- | Master/texmf-dist/source/latex/siunitx/siunitx-number.dtx | 1862 | ||||
-rw-r--r-- | Master/texmf-dist/source/latex/siunitx/siunitx-print.dtx | 767 | ||||
-rw-r--r-- | Master/texmf-dist/source/latex/siunitx/siunitx-table.dtx | 606 | ||||
-rw-r--r-- | Master/texmf-dist/source/latex/siunitx/siunitx-unit.dtx | 2516 | ||||
-rw-r--r-- | Master/texmf-dist/source/latex/siunitx/siunitx-v1.dtx | 85 | ||||
-rw-r--r-- | Master/texmf-dist/source/latex/siunitx/siunitx-v2.dtx | 97 | ||||
-rw-r--r-- | Master/texmf-dist/source/latex/siunitx/siunitx-v3.dtx | 347 | ||||
-rw-r--r-- | Master/texmf-dist/source/latex/siunitx/siunitx.dtx | 10 | ||||
-rw-r--r-- | Master/texmf-dist/source/latex/siunitx/siunitx.ins | 83 |
10 files changed, 6453 insertions, 4 deletions
diff --git a/Master/texmf-dist/source/latex/siunitx/siunitx-angle.dtx b/Master/texmf-dist/source/latex/siunitx/siunitx-angle.dtx new file mode 100644 index 00000000000..c31e07278a4 --- /dev/null +++ b/Master/texmf-dist/source/latex/siunitx/siunitx-angle.dtx @@ -0,0 +1,84 @@ +% \iffalse meta-comment +% +% File: siunitx-angle.dtx Copyright (C) 2016-2017 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 +% +% https://www.latex-project.org/lppl.txt +% +% This file is part of the "siunitx bundle" (The Work in LPPL) +% and all files in that bundle must be distributed together. +% +% The released version of this bundle is available from CTAN. +% +% ----------------------------------------------------------------------- +% +% The development version of the bundle can be found at +% +% https://github.com/josephwright/siunitx +% +% for those people who are interested. +% +% ----------------------------------------------------------------------- +% +%<*driver> +\documentclass{l3doc} +% The next line is needed so that \GetFileInfo will be able to pick up +% version data +\usepackage{siunitx} +\begin{document} + \DocInput{\jobname.dtx} +\end{document} +%</driver> +% \fi +% +% \GetFileInfo{siunitx.sty} +% +% \title{^^A +% \pkg{siunitx-angle} -- Formatting angles^^A +% \thanks{This file describes \fileversion, +% last revised \filedate.}^^A +% } +% +% \author{^^A +% Joseph Wright^^A +% \thanks{^^A +% E-mail: +% \href{mailto:joseph.wright@morningstar2.co.uk} +% {joseph.wright@morningstar2.co.uk}^^A +% }^^A +% } +% +% \date{Released \filedate} +% +% \maketitle +% +% \begin{documentation} +% +% \end{documentation} +% +% \begin{implementation} +% +% \section{\pkg{siunitx-angle} implementation} +% +% Start the \pkg{DocStrip} guards. +% \begin{macrocode} +%<*package> +% \end{macrocode} +% +% Identify the internal prefix (\LaTeX3 \pkg{DocStrip} convention): only +% internal material in this \emph{submodule} should be used directly. +% \begin{macrocode} +%<@@=siunitx_table> +% \end{macrocode} +% +% \begin{macrocode} +%</package> +% \end{macrocode} +% +% \end{implementation} +% +% \PrintIndex
\ No newline at end of file diff --git a/Master/texmf-dist/source/latex/siunitx/siunitx-number.dtx b/Master/texmf-dist/source/latex/siunitx/siunitx-number.dtx new file mode 100644 index 00000000000..63de999adce --- /dev/null +++ b/Master/texmf-dist/source/latex/siunitx/siunitx-number.dtx @@ -0,0 +1,1862 @@ +% \iffalse meta-comment +% +% File: siunitx-number.dtx Copyright (C) 2014-2017 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 +% +% https://www.latex-project.org/lppl.txt +% +% This file is part of the "siunitx bundle" (The Work in LPPL) +% and all files in that bundle must be distributed together. +% +% The released version of this bundle is available from CTAN. +% +% ----------------------------------------------------------------------- +% +% The development version of the bundle can be found at +% +% https://github.com/josephwright/siunitx +% +% for those people who are interested. +% +% ----------------------------------------------------------------------- +% +%<*driver> +\documentclass{l3doc} +% The next line is needed so that \GetFileInfo will be able to pick up +% version data +\usepackage{siunitx} +\begin{document} + \DocInput{\jobname.dtx} +\end{document} +%</driver> +% \fi +% +% \GetFileInfo{siunitx.sty} +% +% \title{^^A +% \pkg{siunitx-number} -- Parsing and formatting numbers^^A +% \thanks{This file describes \fileversion, +% last revised \filedate.}^^A +% } +% +% \author{^^A +% Joseph Wright^^A +% \thanks{^^A +% E-mail: +% \href{mailto:joseph.wright@morningstar2.co.uk} +% {joseph.wright@morningstar2.co.uk}^^A +% }^^A +% } +% +% \date{Released \filedate} +% +% \maketitle +% +% \begin{documentation} +% +% \begin{function}{\siunitx_number_format:nN, \siunitx_number_format:VN} +% \begin{syntax} +% \cs{siunitx_number_format:nN} \Arg{number} \meta{tl~var} +% \end{syntax} +% \end{function} +% +% \begin{function}{\siunitx_number_format:nNN} +% \begin{syntax} +% \cs{siunitx_number_format:nNN} \Arg{number} \meta{tl~var} \meta{marker} +% \end{syntax} +% \end{function} +% +% \begin{function}[TF]{\siunitx_if_number:n} +% \begin{syntax} +% \cs{siunitx_if_number_token:NTF} \Arg{tokens} +% \Arg{true code} \Arg{false code} +% \end{syntax} +% Determines if the \meta{tokens} form a valid number which can be fully +% parsed by \pkg{siunitx}. +% \end{function} +% +% \begin{function}[TF]{\siunitx_if_number_token:N} +% \begin{syntax} +% \cs{siunitx_if_number_token:NTF} \Arg{token} +% \Arg{true code} \Arg{false code} +% \end{syntax} +% Determines if the \meta{token} is valid in a number based on those +% tokens currently set up for detection in a number. +% \end{function} +% +% \end{documentation} +% +% \begin{implementation} +% +% \section{\pkg{siunitx-number} implementation} +% +% Start the \pkg{DocStrip} guards. +% \begin{macrocode} +%<*package> +% \end{macrocode} +% +% Identify the internal prefix (\LaTeX3 \pkg{DocStrip} convention): only +% internal material in this \emph{submodule} should be used directly. +% \begin{macrocode} +%<@@=siunitx_number> +% \end{macrocode} +% +% \subsection{Initial set-up} +% +% Variants not provided by \pkg{expl3}. +% \begin{macrocode} +\cs_generate_variant:Nn \tl_if_blank:nTF { f } +\cs_generate_variant:Nn \tl_if_blank_p:n { f } +\cs_generate_variant:Nn \tl_if_in:NnTF { NV } +% \end{macrocode} +% +% \begin{variable}{\l_@@_tmp_tl} +% Scratch space. +% \begin{macrocode} +\tl_new:N \l_@@_tmp_tl +% \end{macrocode} +% \end{variable} +% +% \subsection{Main formatting routine} +% +% \begin{variable}{\l_@@_formatted_tl} +% A token list for the final formatted result: may or may not be generated +% by the parser, depending on settings which are active. +% \begin{macrocode} +\tl_new:N \l_@@_formatted_tl +% \end{macrocode} +% \end{variable} +% +% \begin{variable}{\l_@@_tab_tl} +% A token list for marking the position of tabular alignments in formatted +% output. +% \begin{macrocode} +\tl_new:N \l_@@_tab_tl +% \end{macrocode} +% \end{variable} +% +% \begin{macro}{\siunitx_number_format:nN, \siunitx_number_format:VN} +% \begin{macro}{\siunitx_number_format:nNN} +% \begin{macro}{\@@_format:nN} +% \begin{macrocode} +\cs_new_protected:Npn \siunitx_number_format:nN #1#2 + { + \tl_clear:N \l_@@_tab_tl + \@@_format:nN {#1} #2 + } +\cs_generate_variant:Nn \siunitx_number_format:nN { V } +\cs_new_protected:Npn \siunitx_number_format:nNN #1#2#3 + { + \tl_set:Nn \l_@@_tab_tl {#3} + \@@_format:nN {#1} #2 + } +\cs_new_protected:Npn \@@_format:nN #1#2 + { + \group_begin: + \@@_parse:n {#1} + \@@_format: + \exp_args:NNNV \group_end: + \tl_set:Nn #2 \l_@@_formatted_tl + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \subsection{Parsing numbers} +% +% Before numbers can be manipulated or formatted they need to be parsed into +% an internal form. In particular, if multiple code paths are to be avoided, +% it is necessary to do such parsing even for relatively simple cases such +% as converting |1e10| to |1 \times 10^{10}|. +% +% Storing the result of such parsing can be done in a number of ways. In the +% first version of \pkg{siunitx} a series of separate data stores were used. +% This is potentially quite fast (as recovery of items relies only on \TeX{}'s +% hash table) but makes managing the various data entries somewhat tedious and +% error-prone. For version two of the package, a single data structure +% (property list) was used for each part of the parsed number. Whilst this is +% easy to manage and extend, it is somewhat slower as at a \TeX{} level there +% are repeated pack--unpack steps. In particular, the fact that there are a +% limited number of items to track for a \enquote{number} means that a more +% efficient approach is desirable (contrast parsing units, which is open-ended +% and therefore fits well with using a property list). +% +% To allow for complex numbers, two parallel data structures are used, one for +% the real part and one for the imaginary part. If the part is entirely absent +% then the data structures are left empty. Within each part, the structure +% is +% \begin{quote} +% \marg{comparator}\meta{sign}\marg{integer}\marg{decimal} +% \marg{uncertainty}\\ +% \meta{exponent sign}\marg{exponent} +% \end{quote} +% where the two sign parts must be single tokens and all other components +% must be given in braces. \emph{All} of the components must be present in +% a stored number (\emph{i.e.}~at the end of parsing). The number must have +% at least one digit for both the \meta{integer} and \meta{exponent} parts. +% +% \begin{variable} +% { +% \l_@@_expression_bool , +% \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_sign_tl , +% \l_@@_input_uncert_sign_tl +% } +% \begin{macro}[EXP]{\@@_expression:n} +% Options which determine the various valid parts of a parsed number. +% \begin{macrocode} +\keys_define:nn { siunitx } + { + evaluate-expression .bool_set:N = + \l_@@_expression_bool , + expression .code:n = + \cs_set:Npn \@@_expression:n ##1 {#1} , + 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-signs .tl_set:N = + \l_@@_input_sign_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} } + } + } + } +\cs_new:Npn \@@_expression:n #1 { } +% \end{macrocode} +% \end{macro} +% \end{variable} +% +% \begin{variable}{\l_@@_arg_tl} +% The input argument or a part thereof, depending on the position in +% the parsing routine. +% \begin{macrocode} +\tl_new:N \l_@@_arg_tl +% \end{macrocode} +% \end{variable} +% +% \begin{variable}{\l_@@_comparator_tl} +% A comparator, if found, is held here. +% \begin{macrocode} +\tl_new:N \l_@@_comparator_tl +% \end{macrocode} +% \end{variable} +% +% \begin{variable}{\l_@@_exponent_tl} +% The exponent part of a parsed number. It is easiest to find this +% relatively early in the parsing process, but as it needs to go at +% the end of the internal format is held separately until required. +% \begin{macrocode} +\tl_new:N \l_@@_exponent_tl +% \end{macrocode} +% \end{variable} +% +% \begin{variable}{\l_@@_flex_tl} +% When parsing for a separate uncertainty or complex number, the nature +% of the grabbed part cannot be determined until the end of the number. +% To avoid abusing the storage areas, this dedicated one is used for +% \enquote{flexible} cases. +% \begin{macrocode} +\tl_new:N \l_@@_flex_tl +% \end{macrocode} +% \end{variable} +% +% \begin{variable}{\l_@@_imaginary_tl, \l_@@_real_tl} +% Used to hold the real and imaginary parts of a number in the standardised +% format. +% \begin{macrocode} +\tl_new:N \l_@@_imaginary_tl +\tl_new:N \l_@@_real_tl +% \end{macrocode} +% \end{variable} +% +% \begin{variable}{\l_@@_input_tl} +% The numerical input exactly as given by the user. +% \begin{macrocode} +\tl_new:N \l_@@_input_tl +% \end{macrocode} +% \end{variable} +% +% \begin{variable}{\l_@@_partial_tl} +% To avoid needing to worry about the fact that the final data stores are +% somewhat tricky to add to token-by-token, a simple store is used to build +% up the parsed part of a number before transferring in one go. +% \begin{macrocode} +\tl_new:N \l_@@_partial_tl +% \end{macrocode} +% \end{variable} +% +% \begin{variable}{\l_@@_validate_bool} +% Used to set up for validation with no error production. +% \begin{macrocode} +\bool_new:N \l_@@_validate_bool +% \end{macrocode} +% \end{variable} +% +% \begin{macro}{\@@_parse:n} +% After some initial set up, the parser expands the input and then replaces +% as far as possible tricky tokens with ones that can be handled using +% delimited arguments. The parser begins with the assumption that the input +% is a real number. To avoid multiple conditionals here, the parser is +% set up as a chain of commands initially, with a loop only later. This +% avoids more conditionals than are necessary. +% \begin{macrocode}q +\cs_new_protected:Npn \@@_parse:n #1 + { + \tl_clear:N \l_@@_imaginary_tl + \tl_clear:N \l_@@_real_tl + \protected@edef \l_@@_arg_tl + { + \bool_if:NTF \l_@@_expression_bool + { \fp_eval:n { \@@_expression:n {#1} } } + {#1} + } + \tl_set_eq:NN \l_@@_input_tl \l_@@_arg_tl + \@@_parse_replace: + \tl_if_empty:NF \l_@@_arg_tl + { \@@_parse_comparator: } + \@@_parse_check: + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_parse_check:} +% After the loop there is one case that might need tidying up. If a +% separated uncertainty was found it will be currently in \cs{l_@@_flex_tl} +% and needs moving. A series of tests pick up that case, then the check is +% made that some content was found for at least one of the real or imaginary +% parts of the number. +% \begin{macrocode} +\cs_new_protected:Npn \@@_parse_check: + { + \tl_if_empty:NF \l_@@_flex_tl + { + \bool_lazy_and:nnTF + { + \tl_if_blank_p:f + { \exp_after:wN \use_iv:nnnn \l_@@_real_tl } + } + { + \tl_if_blank_p:f + { \exp_after:wN \use_iv:nnnn \l_@@_flex_tl } + } + { + \tl_set:Nx \l_@@_tmp_tl + { \exp_after:wN \use_i:nnnn \l_@@_flex_tl } + \tl_if_in:NVTF \l_@@_input_uncert_sign_tl + \l_@@_tmp_tl + { \@@_parse_combine_uncert: } + { \tl_clear:N \l_@@_real_tl } + } + { \tl_clear:N \l_@@_real_tl } + } + \bool_lazy_and:nnTF + { \tl_if_empty_p:N \l_@@_real_tl } + { \tl_if_empty_p:N \l_@@_imaginary_tl } + { + \bool_if:NF \l_@@_validate_bool + { + \msg_error:nnx { siunitx } { number / invalid-input } + { \exp_not:V \l_@@_input_tl } + } + } + { \@@_parse_finalise: } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_parse_combine_uncert:} +% \begin{macro}{\@@_parse_combine_uncert_auxi:NnnnNnnn} +% \begin{macro} +% { +% \@@_parse_combine_uncert_auxii:nnnnn, +% \@@_parse_combine_uncert_auxii:fnnnn +% } +% \begin{macro} +% { +% \@@_parse_combine_uncert_auxiii:nnnnnn, +% \@@_parse_combine_uncert_auxiii:fnnnnn +% } +% \begin{macro}{\@@_parse_combine_uncert_auxiv:nnnn} +% \begin{macro}[EXP]{\@@_parse_combine_uncert_auxv:w} +% \begin{macro}[EXP]{\@@_parse_combine_uncert_auxvi:w} +% Conversion of a second numerical part to an uncertainty needs a bit of +% work. The first step is to extract the useful information from the two +% stores: the sign, integer and decimal parts from the real number and the +% integer and decimal parts from the second number. That is done using the +% input stack to avoid lots of assignments. +% \begin{macrocode} +\cs_new_protected:Npn \@@_parse_combine_uncert: + { + \exp_after:wN \exp_after:wN \exp_after:wN + \@@_parse_combine_uncert_auxi:NnnnNnnn + \exp_after:wN \l_@@_real_tl \l_@@_flex_tl + } +% \end{macrocode} +% Here, |#4|, |#5| and |#8| are all junk arguments simply there to mop up +% tokens, while |#1| will be recovered later from \cs{l_@@_real_tl} so does +% not need to be passed about. The difference in places between the two +% decimal parts is now found: this is done just once to avoid having to +% parse token lists twice. The value is then used to generate a number of +% filler |0| tokens, and these are added to the appropriate part of the +% number. Finally, everything is recombined: the integer part only needs +% a test to avoid an empty main number. +% \begin{macrocode} +\cs_new_protected:Npn + \@@_parse_combine_uncert_auxi:NnnnNnnn #1#2#3#4#5#6#7#8 + { + \int_compare:nNnTF { \tl_count:n {#6} } > { \tl_count:n {#2} } + { + \tl_clear:N \l_@@_real_tl + \tl_clear:N \l_@@_flex_tl + } + { + \@@_parse_combine_uncert_auxii:fnnnn + { \int_eval:n { \tl_count:n {#3} - \tl_count:n {#7} } } + {#2} {#3} {#6} {#7} + } + } +\cs_new_protected:Npn + \@@_parse_combine_uncert_auxii:nnnnn #1 + { + \@@_parse_combine_uncert_auxiii:fnnnnn + { \prg_replicate:nn { \int_abs:n {#1} } { 0 } } + {#1} + } +\cs_generate_variant:Nn \@@_parse_combine_uncert_auxii:nnnnn { f } +\cs_new_protected:Npn + \@@_parse_combine_uncert_auxiii:nnnnnn #1#2#3#4#5#6 + { + \int_compare:nNnTF {#2} > 0 + { + \@@_parse_combine_uncert_auxiv:nnnn + {#3} {#4} {#5} { #6 #1 } + } + { + \@@_parse_combine_uncert_auxiv:nnnn + {#3} { #4 #1 } {#5} {#6} + } + } +\cs_generate_variant:Nn + \@@_parse_combine_uncert_auxiii:nnnnnn { f } +\cs_new_protected:Npn + \@@_parse_combine_uncert_auxiv:nnnn #1#2#3#4 + { + \tl_set:Nx \l_@@_real_tl + { + \tl_head:V \l_@@_real_tl + { \exp_not:n {#1} } + { + \bool_lazy_and:nnTF + { \tl_if_blank_p:n {#2} } + { ! \tl_if_blank_p:n {#4} } + { 0 } + { \exp_not:n {#2} } + } + { + \@@_parse_combine_uncert_auxv:w #3#4 + \q_recursion_tail \q_recursion_stop + } + } + } +% \end{macrocode} +% A short routine to remove any leading zeros in the uncertainty part, +% which are not needed for the compact representation used by the module. +% \begin{macrocode} +\cs_new:Npn \@@_parse_combine_uncert_auxv:w #1 + { + \quark_if_recursion_tail_stop:N #1 + \str_if_eq:nnTF {#1} { 0 } + { \@@_parse_combine_uncert_auxv:w } + { \@@_parse_combine_uncert_auxvi:w #1 } + } +\cs_new:Npn \@@_parse_combine_uncert_auxvi:w + #1 \q_recursion_tail \q_recursion_stop + { \exp_not:n {#1} } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@@_parse_comparator:} +% \begin{macro}{\@@_parse_comparator_aux:Nw} +% A comparator has to be the very first token in the input. A such, the +% test for this can be very fast: grab the first token, do a check and +% if appropriate store the result. +% \begin{macrocode} +\cs_new_protected:Npn \@@_parse_comparator: + { + \exp_after:wN \@@_parse_comparator_aux:Nw + \l_@@_arg_tl \q_stop + } +\cs_new_protected:Npn \@@_parse_comparator_aux:Nw #1#2 \q_stop + { + \tl_if_in:NnTF \l_@@_input_comparator_tl {#1} + { + \tl_set:Nn \l_@@_comparator_tl {#1} + \tl_set:Nn \l_@@_arg_tl {#2} + } + { \tl_clear:N \l_@@_comparator_tl } + \tl_if_empty:NF \l_@@_arg_tl + { \@@_parse_sign: } + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@@_parse_exponent:} +% \begin{macro}{\@@_parse_exponent_aux:w} +% \begin{macro}{\@@_parse_exponent_aux:nn} +% \begin{macro}{\@@_parse_exponent_aux:Nw} +% \begin{macro}{\@@_parse_exponent_aux:Nn} +% \begin{macro} +% {\@@_parse_exponent_zero_test:N, \@@_parse_exponent_check:N} +% \begin{macro}{\@@_parse_exponent_cleanup:N} +% An exponent part of a number has to come at the end and can only occur +% once. Thus it is relatively easy to parse. First, there is a check that +% an exponent part is allowed, and if so a split is made (the previous +% part of the chain checks that there is some content in \cs{l_@@_arg_tl} +% before calling this function). After splitting, if there is no exponent +% then simply save a default. Otherwise, check for a sign and then store +% either this or an assumed |+| and the digits after a check that nothing +% else is present after the~|e|. The only slight complication to all of +% this is allowing an arbitrary token in the input to represent the exponent: +% this is done by setting any exponent tokens to the first of the allowed +% list, then using that in a delimited argument set up. Once an exponent +% part is found, there is a loop to check that each of the tokens is a digit +% then a tidy up step to remove any leading zeros. +% \begin{macrocode} +\cs_new_protected:Npn \@@_parse_exponent: + { + \tl_if_empty:NTF \l_@@_input_exponent_tl + { \tl_set:Nn \l_@@_exponent_tl { +0 } } + { + \tl_set:Nx \l_@@_tmp_tl + { \tl_head:V \l_@@_input_exponent_tl } + \tl_map_inline:Nn \l_@@_input_exponent_tl + { + \tl_replace_all:NnV \l_@@_arg_tl + {##1} \l_@@_tmp_tl + } + \use:x + { + \cs_set_protected:Npn + \exp_not:N \@@_parse_exponent_aux:w + ####1 \exp_not:V \l_@@_tmp_tl + ####2 \exp_not:V \l_@@_tmp_tl + ####3 \exp_not:N \q_stop + } + { \@@_parse_exponent_aux:nn {##1} {##2} } + \use:x + { + \@@_parse_exponent_aux:w + \exp_not:V \l_@@_arg_tl + \exp_not:V \l_@@_tmp_tl \exp_not:N \q_nil + \exp_not:V \l_@@_tmp_tl \exp_not:N \q_stop + } + } + } +\cs_new_protected:Npn \@@_parse_exponent_aux:w { } +\cs_new_protected:Npn \@@_parse_exponent_aux:nn #1#2 + { + \quark_if_nil:nTF {#2} + { \tl_set:Nn \l_@@_exponent_tl { +0 } } + { + \tl_set:Nn \l_@@_arg_tl {#1} + \tl_if_blank:nTF {#2} + { \tl_clear:N \l_@@_real_tl } + { \@@_parse_exponent_aux:Nw #2 \q_stop } + } + \tl_if_empty:NF \l_@@_real_tl + { \@@_parse_loop: } + } +\cs_new_protected:Npn \@@_parse_exponent_aux:Nw #1#2 \q_stop + { + \tl_if_in:NnTF \l_@@_input_sign_tl {#1} + { \@@_parse_exponent_aux:Nn #1 {#2} } + { \@@_parse_exponent_aux:Nn + {#1#2} } + \tl_if_empty:NT \l_@@_exponent_tl + { \tl_clear:N \l_@@_real_tl } + } +\cs_new_protected:Npn \@@_parse_exponent_aux:Nn #1#2 + { + \tl_set:Nn \l_@@_exponent_tl { #1 } + \tl_if_blank:nTF {#2} + { \tl_clear:N \l_@@_real_tl } + { + \@@_parse_exponent_zero_test:N #2 + \q_recursion_tail \q_recursion_stop + } + } +\cs_new_protected:Npn \@@_parse_exponent_zero_test:N #1 + { + \quark_if_recursion_tail_stop_do:Nn #1 + { \tl_set:Nn \l_@@_exponent_tl { +0 } } + \str_if_eq:nnTF {#1} { 0 } + { \@@_parse_exponent_zero_test:N } + { \@@_parse_exponent_check:N #1 } + } +\cs_new_protected:Npn \@@_parse_exponent_check:N #1 + { + \quark_if_recursion_tail_stop:N #1 + \tl_if_in:NnTF \l_@@_input_digit_tl {#1} + { + \tl_put_right:Nn \l_@@_exponent_tl {#1} + \@@_parse_exponent_check:N + } + { \@@_parse_exponent_cleanup:wN } + } +\cs_new_protected:Npn \@@_parse_exponent_cleanup:wN + #1 \q_recursion_stop + { \tl_clear:N \l_@@_real_tl } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@@_parse_replace:} +% \begin{macro}{\@@_parse_replace_aux:nN} +% \begin{macro}{\@@_parse_replace_sign:} +% \begin{variable}{\c_@@_parse_sign_replacement_tl} +% There are two parts to the replacement code. First, any active +% hyphens signs are normalised: these can come up with some packages and +% cause issues. Multi-token signs then are converted to the single token +% equivalents so that everything else can work on a one token basis. +% \begin{macrocode} +\cs_new_protected:Npn \@@_parse_replace: + { + \@@_parse_replace_minus: + \exp_last_unbraced:NV \@@_parse_replace_aux:nN + \c_@@_parse_sign_replacement_tl + { ? } \q_recursion_tail + \q_recursion_stop + } +\cs_set_protected:Npn \@@_parse_replace_aux:nN #1#2 + { + \quark_if_recursion_tail_stop:N #2 + \tl_replace_all:Nnn \l_@@_arg_tl {#1} {#2} + \@@_parse_replace_aux:nN + } +\tl_const:Nn \c_@@_parse_sign_replacement_tl + { + { -+ } \mp + { +- } \pm + { << } \ll + { <= } \le + { >> } \gg + { >= } \ge + } +\group_begin: + \char_set_catcode_active:N \- + \cs_new_protected:Npx \@@_parse_replace_minus: + { + \tl_replace_all:Nnn \exp_not:N \l_@@_arg_tl + { \exp_not:N - } { \token_to_str:N - } + } +\group_end: +% \end{macrocode} +% \end{variable} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@@_parse_finalise:} +% \begin{macro}{\@@_parse_finalise_aux:N} +% \begin{macro}{\@@_parse_finalise_aux:Nw} +% Combine all of the bits of a number together: both the real and +% imaginary parts contain all of the data. +% \begin{macrocode} +\cs_new_protected:Npn \@@_parse_finalise: + { + \@@_parse_finalise_aux:N \l_@@_real_tl + \@@_parse_finalise_aux:N \l_@@_imaginary_tl + } +\cs_new_protected:Npn \@@_parse_finalise_aux:N #1 + { + \tl_if_empty:NF #1 + { + \tl_set:Nx #1 + { + { \exp_not:V \l_@@_comparator_tl } + \exp_not:V #1 + \exp_after:wN \@@_parse_finalise_aux:Nw + \l_@@_exponent_tl \q_stop + } + } + } +\cs_new:Npn \@@_parse_finalise_aux:Nw #1#2 \q_stop + { + \exp_not:N #1 + { \exp_not:n {#2} } + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@@_parse_loop:} +% \begin{macro}{\@@_parse_loop_first:N} +% \begin{macro}{\@@_parse_loop_main:NNNNN} +% \begin{macro}{\@@_parse_loop_main_end:NN} +% \begin{macro}{\@@_parse_loop_main_digit:NNNNN} +% \begin{macro}{\@@_parse_loop_main_decimal:NN} +% \begin{macro}{\@@_parse_loop_main_uncert:NNN} +% \begin{macro}{\@@_parse_loop_main_complex:N} +% \begin{macro}{\@@_parse_loop_main_sign:NNN} +% \begin{macro}{\@@_parse_loop_main_store:NNN} +% \begin{macro}{\@@_parse_loop_after_decimal:NNN} +% \begin{macro}{\@@_parse_loop_uncert:NNNNN} +% \begin{macro}{\@@_parse_loop_after_uncert:NNN} +% \begin{macro}{\@@_parse_loop_root_swap:NNwNN} +% \begin{macro}{\@@_parse_loop_complex_cleanup:wN} +% \begin{macro}{\@@_parse_loop_break:wN} +% At this stage, the partial input \cs{l_@@_arg_tl} will contain any +% mantissa, which may contain an uncertainty or complex part. Parsing this +% and allowing for all of the different formats possible is best done using +% a token-by-token approach. However, as at each stage only a subset of +% tokens are valid, the approach take is to use a set of semi-dedicated +% functions to parse different components along with switches to allow a +% sensible amount of code sharing. +% \begin{macrocode} +\cs_new_protected:Npn \@@_parse_loop: + { + \tl_clear:N \l_@@_partial_tl + \exp_after:wN \@@_parse_loop_first:NNN + \exp_after:wN \l_@@_real_tl \exp_after:wN \c_true_bool + \l_@@_arg_tl + \q_recursion_tail \q_recursion_stop + } +% \end{macrocode} +% The very first token of the input is handled with a dedicated function. +% Valid cases here are +% \begin{itemize} +% \item Entirely blank if the original input was for example |+e10|: +% simply clean up if in the integer part of issue an error if in +% a second part (complex number, \emph{etc.}). +% \item An integer part digit: pass through to the main collection +% routine. +% \item A decimal marker: store an empty integer part and move to +% the main collection routine for a decimal part. +% \item A complex root token: shuffle to the end of the input. +% \end{itemize} +% Anything else is invalid and sends the code to the abort function. +% \begin{macrocode} +\cs_new_protected:Npn \@@_parse_loop_first:NNN #1#2#3 + { + \quark_if_recursion_tail_stop_do:Nn #3 + { + \bool_if:NTF #2 + { \tl_put_right:Nn #1 { { 1 } { } { } } } + { \@@_parse_loop_break:wN \q_recursion_stop } + } + \tl_if_in:NnTF \l_@@_input_digit_tl {#3} + { + \@@_parse_loop_main:NNNNN + #1 \c_true_bool \c_false_bool #2 #3 + } + { + \tl_if_in:NnTF \l_@@_input_decimal_tl {#3} + { + \tl_put_right:Nn #1 { { 0 } } + \@@_parse_loop_after_decimal:NNN #1 #2 + } + { + \tl_if_in:NnTF \l_@@_input_complex_tl {#3} + { \@@_parse_loop_root_swap:NNwNN #1 #3 } + { \@@_parse_loop_break:wN } + } + } + } +% \end{macrocode} +% A single function is used to cover the \enquote{main} part of numbers: +% finding real, complex or separated uncertainty parts and covering both +% the integer and decimal components. This works because these elements +% share a lot of concepts: a small number of switches can be used to +% differentiate between them. To keep the code at least somewhat readable, +% this main function deals with the validity testing but hands off other +% tasks to dedicated auxiliaries for each case. +% +% The possibilities are +% \begin{itemize} +% \item The number terminates, meaning that some digits were collected +% and everything is simply tidied up (as far as the loop is concerned). +% \item A digit is found: this is the common case and leads to a storage +% auxiliary (which handles non-significant zeros). +% \item A decimal marker is found: only valid in the integer part and +% there leading to a store-and-switch situation. +% \item An open-uncertainty token: switch to the dedicated collector +% for uncertainties. +% \item A complex root token: store the current number as an imaginary +% part and terminate the loop. +% \item A sign token (if allowed): stop collecting this number and +% restart collection for the second part. +% \end{itemize} +% \begin{macrocode} +\cs_new_protected:Npn \@@_parse_loop_main:NNNNN #1#2#3#4#5 + { + \quark_if_recursion_tail_stop_do:Nn #5 + { \@@_parse_loop_main_end:NN #1#2 } + \tl_if_in:NnTF \l_@@_input_digit_tl {#5} + { \@@_parse_loop_main_digit:NNNNN #1#2#3#4#5 } + { + \tl_if_in:NnTF \l_@@_input_decimal_tl {#5} + { + \bool_if:NTF #2 + { \@@_parse_loop_main_decimal:NN #1 #4 } + { \@@_parse_loop_break:wN } + } + { + \tl_if_in:NnTF \l_@@_input_uncert_open_tl {#5} + { \@@_parse_loop_main_uncert:NNN #1#2 #4 } + { + \tl_if_in:NnTF \l_@@_input_complex_tl {#5} + { + \@@_parse_loop_main_store:NNN + #1 #2 \c_true_bool + \@@_parse_loop_main_complex:N #1 + } + { + \bool_if:NTF #4 + { + \tl_if_in:NnTF \l_@@_input_sign_tl {#5} + { + \@@_parse_loop_main_sign:NNN + #1#2 #5 + } + { \@@_parse_loop_break:wN } + } + { \@@_parse_loop_break:wN } + } + } + } + } + } +% \end{macrocode} +% If the main loop finds the end marker then there is a tidy up phase. +% The current partial number is stored either as the integer or decimal, +% depending on the setting for the indicator switch. For the integer +% part, if no number has been collected then one or more non-significant +% zeros have been dropped. Exactly one zero is therefore needed to make +% sure the parsed result is correct. +% \begin{macrocode} +\cs_new_protected:Npn \@@_parse_loop_main_end:NN #1#2 + { + \bool_lazy_and:nnT + {#2} { \tl_if_empty_p:N \l_@@_partial_tl } + { \tl_set:Nn \l_@@_partial_tl { 0 } } + \tl_put_right:Nx #1 + { + { \exp_not:V \l_@@_partial_tl } + \bool_if:NT #2 { { } } + { } + } + } +% \end{macrocode} +% The most common case for the main loop collector is to find a digit. +% Here, in the integer part it is possible that zeros are non-significant: +% that is handled using a combination of a switch and a string test. Other +% than that, the situation here is simple: store the input and loop. +% \begin{macrocode} +\cs_new_protected:Npn \@@_parse_loop_main_digit:NNNNN #1#2#3#4#5 + { + \bool_lazy_or:nnTF + {#3} { ! \str_if_eq_p:nn {#5} { 0 } } + { + \tl_put_right:Nn \l_@@_partial_tl {#5} + \@@_parse_loop_main:NNNNN #1 #2 \c_true_bool #4 + } + { \@@_parse_loop_main:NNNNN #1 #2 \c_false_bool #4 } + } +% \end{macrocode} +% When a decimal marker was found, move the integer part to the +% store and then go back to the loop with the flags set correctly. +% There is the case of non-significant zeros to cover before that, of course. +% \begin{macrocode} +\cs_new_protected:Npn \@@_parse_loop_main_decimal:NN #1#2 + { + \@@_parse_loop_main_store:NNN #1 \c_false_bool \c_false_bool + \@@_parse_loop_after_decimal:NNN #1 #2 + } +% \end{macrocode} +% Starting an uncertainty part means storing the number to date as in other +% cases, with the possibility of a blank decimal part allowed for. The +% uncertainty itself is collected by a dedicated function as it is extremely +% restricted. +% \begin{macrocode} +\cs_new_protected:Npn \@@_parse_loop_main_uncert:NNN #1#2#3 + { + \@@_parse_loop_main_store:NNN #1 #2 \c_false_bool + \@@_parse_loop_uncert:NNNNN + #1 \c_true_bool \c_false_bool #3 + } +% \end{macrocode} +% A complex root token has to be at the end of the input (leading ones +% are dealt with specially). Thus after moving the data to the correct +% place there is a hand-off to a cleanup function. The case where only the +% complex root token was given is covered by +% \cs{@@_parse_loop_root_swap:NNwNN}. +% \begin{macrocode} +\cs_new_protected:Npn \@@_parse_loop_main_complex:N #1 + { + \tl_set_eq:NN \l_@@_imaginary_tl #1 + \tl_clear:N #1 + \@@_parse_loop_complex_cleanup:wN + } +% \end{macrocode} +% If a sign is found, terminate the current number, store the sign as the +% first token of the second part and go back to do the dedicated first-token +% function. +% \begin{macrocode} +\cs_new_protected:Npn \@@_parse_loop_main_sign:NNN #1#2#3 + { + \@@_parse_loop_main_store:NNN #1 #2 \c_true_bool + \tl_set:Nn \l_@@_flex_tl {#3} + \@@_parse_loop_first:NNN + \l_@@_flex_tl \c_false_bool + } +% \end{macrocode} +% A common auxiliary for the various non-digit token functions: tidy up the +% integer and decimal parts of a number. Here, the two flags are used to +% indicate if empty decimal and uncertainty parts should be included in +% the storage cycle. +% \begin{macrocode} +\cs_new_protected:Npn \@@_parse_loop_main_store:NNN #1#2#3 + { + \tl_if_empty:NT \l_@@_partial_tl + { \tl_set:Nn \l_@@_partial_tl { 0 } } + \tl_put_right:Nx #1 + { + { \exp_not:V \l_@@_partial_tl } + \bool_if:NT #2 { { } } + \bool_if:NT #3 { { } } + } + \tl_clear:N \l_@@_partial_tl + } +% \end{macrocode} +% After a decimal marker there has to be a digit if there wasn't one before +% it. That is handled by using a dedicated function, which checks for +% an empty integer part first then either simply hands off or looks for +% a digit. +% \begin{macrocode} +\cs_new_protected:Npn \@@_parse_loop_after_decimal:NNN #1#2#3 + { + \tl_if_blank:fTF { \exp_after:wN \use_none:n #1 } + { + \quark_if_recursion_tail_stop_do:Nn #3 + { \@@_parse_loop_break:wN \q_recursion_stop } + \tl_if_in:NnTF \l_@@_input_digit_tl {#1} + { + \tl_put_right:Nn \l_@@_partial_tl {#3} + \@@_parse_loop_main:NNNNN + #1 \c_false_bool \c_true_bool #2 + } + { \@@_parse_loop_break:wN } + } + { + \@@_parse_loop_main:NNNNN + #1 \c_false_bool \c_true_bool #2 #3 + } + } +% \end{macrocode} +% Inside the brackets for an uncertainty the range of valid choices is +% very limited. Either the token is a digit, in which case there is a +% test to look for non-significant zeros, or it is a closing bracket. The +% latter is not valid for the very first token, which is handled using a +% switch (it's a simple enough difference). +% \begin{macrocode} +\cs_new_protected:Npn \@@_parse_loop_uncert:NNNNN #1#2#3#4#5 + { + \quark_if_recursion_tail_stop_do:Nn #5 + { \@@_parse_loop_break:wN \q_recursion_stop } + \tl_if_in:NnTF \l_@@_input_digit_tl {#5} + { + \bool_lazy_or:nnTF + {#3} { ! \str_if_eq_p:nn {#5} { 0 } } + { + \tl_put_right:Nn \l_@@_partial_tl {#5} + \@@_parse_loop_uncert:NNNNN + #1 \c_false_bool \c_true_bool #4 + } + { + \@@_parse_loop_uncert:NNNNN + #1 \c_false_bool \c_false_bool #4 + } + } + { + \tl_if_in:NnTF \l_@@_input_uncert_close_tl {#5} + { + \bool_if:NTF #2 + { \@@_parse_loop_break:wN } + { + \@@_parse_loop_main_store:NNN #1 + \c_false_bool \c_false_bool + \@@_parse_loop_after_uncert:NNN #1 #3 + } + } + { \@@_parse_loop_break:wN } + } + } +% \end{macrocode} +% After a bracketed uncertainty there are only a very small number of +% valid choices. The number can end, there can be a complex root token +% or there can be a sign. The latter is only allowed if the part being +% parsed at the moment was the first part of the number. The case where +% there is no root symbol but there should have been is cleared up after +% the loop code, so at this stage there is no check. +% \begin{macrocode} +\cs_new_protected:Npn \@@_parse_loop_after_uncert:NNN #1#2#3 + { + \quark_if_recursion_tail_stop:N #3 + \tl_if_in:NnTF \l_@@_input_complex_tl {#3} + { \@@_parse_loop_main_complex:N #1 } + { + \bool_if:NTF #2 + { + \tl_if_in:NnTF \l_@@_input_sign_tl {#3} + { + \tl_set:Nn \l_@@_flex_tl {#3} + \@@_parse_loop_first:NNN + \l_@@_flex_tl \c_false_bool + } + { \@@_parse_loop_break:wN } + } + { \@@_parse_loop_break:wN } + } + } +% \end{macrocode} +% When the complex root symbol comes at the start of the number rather than +% at the end, the easiest approach is to shuffle it to the \enquote{normal} +% position. As the exponent has already been removed, this must be the last +% token of the input and any duplication will be picked up. The case where +% just a complex root token has to be covered: in that situation, there is +% an implicit |1| to store after which the loop stops. +% \begin{macrocode} +\cs_new_protected:Npn \@@_parse_loop_root_swap:NNwNN #1#2#3 + \q_recursion_tail \q_recursion_stop + { + \tl_if_blank:nTF {#3} + { + \tl_set:Nx \l_@@_imaginary_tl + { + \exp_not:V #1 + { 1 } { } { } + } + \tl_clear:N #1 + } + { + \use:x + { + \tl_clear:N \exp_not:N #1 + \tl_set:Nn \exp_not:N \l_@@_flex_tl { \exp_not:V #1 } + } + \@@_parse_loop_first:NNN + \l_@@_flex_tl \c_false_bool + #3 #2 \q_recursion_tail \q_recursion_stop + } + } +% \end{macrocode} +% Nothing is allowed after a complex root token: check and if there is +% kill the parsing. +% \begin{macrocode} +\cs_new_protected:Npn \@@_parse_loop_complex_cleanup:wN + #1 \q_recursion_tail \q_recursion_stop + { + \tl_if_blank:nF {#1} + { \@@_parse_loop_break:wN \q_recursion_stop } + } +% \end{macrocode} +% Something is not right: remove all of the remaining tokens from the +% number and clear the storage areas as a signal for the next part of the +% code. +% \begin{macrocode} +\cs_new_protected:Npn \@@_parse_loop_break:wN + #1 \q_recursion_stop + { + \tl_clear:N \l_@@_imaginary_tl + \tl_clear:N \l_@@_flex_tl + \tl_clear:N \l_@@_real_tl + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@@_parse_sign:} +% \begin{macro}{\@@_parse_sign_aux:Nw} +% The first token of a number after a comparator could be a sign. A quick +% check is made and if found stored; if there is no sign then the internal +% format requires that |+| is used. For the number to be valid it has to be +% more than just a sign, so the next part of the chain is only called if that +% is the case. +% \begin{macrocode} +\cs_new_protected:Npn \@@_parse_sign: + { + \exp_after:wN \@@_parse_sign_aux:Nw + \l_@@_arg_tl \q_stop + } +\cs_new_protected:Npn \@@_parse_sign_aux:Nw #1#2 \q_stop + { + \tl_if_in:NnTF \l_@@_input_sign_tl {#1} + { + \tl_set:Nn \l_@@_arg_tl {#2} + \tl_set:Nn \l_@@_real_tl {#1} + } + { \tl_set:Nn \l_@@_real_tl { + } } + \tl_if_empty:NTF \l_@@_arg_tl + { \tl_clear:N \l_@@_real_tl } + { \@@_parse_exponent: } + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \subsection{Processing numbers} +% +% \begin{variable} +% { +% \l_@@_round_half_up_bool , +% \l_@@_round_min_tl , +% \l_@@_round_mode_tl , +% \l_@@_round_precision_int +% } +% \begin{macrocode} +\keys_define:nn { siunitx } + { + 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-minimum .tl_set:N = + \l_@@_round_min_tl , + round-mode .choice: , + round-mode / figures .code:n = + { \tl_set:Nn \_@@_round_mode_tl { figures } } , + round-mode / none .code:n = + { \tl_set:Nn \_@@_round_mode_tl { none } } , + round-mode / places .code:n = + { \tl_set:Nn \_@@_round_mode_tl { places } } , + round-mode / uncertainty .code:n = + { \tl_set:Nn \_@@_round_mode_tl { uncertainty } } , + round-precision .int_set:N = + \l_@@_round_precision_int , + } +\bool_new:N \l_@@_round_half_up_bool +\tl_new:N \_@@_round_mode_tl +% \end{macrocode} +% \end{variable} +% +% \begin{macro}{\@@_round:} +% \begin{macro}{\@@_round:N} +% \begin{macro}{\@@_round_none:nNnnnNn} +% \begin{macrocode} +\cs_new_protected:Npn \@@_round: + { + \@@_round:N \l_@@_real_tl + \@@_round:N \l_@@_imaginary_tl + } +\cs_new_protected:Npn \@@_round:N #1 + { + \tl_if_empty:NF #1 + { + \tl_set:Nx #1 + { + \cs:w + @@_round_ \_@@_round_mode_tl :nNnnnNn + \exp_after:wN + \cs_end: #1 + } + } + } +\cs_new:Npn \@@_round_none:nNnnnNn #1#2#3#4#5#6#7 + { \exp_not:n { {#1} #2 {#3} {#4} {#5} #6 {#7} } } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}[EXP]{\@@_round_figures:nNnnnNn} +% \begin{macrocode} +\cs_new:Npn \@@_round_figures:nNnnnNn #1#2#3#4#5#6#7 + { + \tl_if_blank:nTF {#5} + { + \int_compare:nNnTF \l_@@_round_precision_int > 0 + { } + { { } + { 0 } { } { } + { 0 } } + } + { \exp_not:n { {#1} #2 {#3} {#4} {#5} #6 {#7} } } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[EXP]{\@@_round_places:nNnnnNn} +% \begin{macro}[EXP] +% {\@@_round_places_decimal:nNnnNn, \@@_round_places_integer:nNnnNn} +% The first step when rounding to a fixed number of places is to establish +% if this is in the decimal or integer parts. The two require different +% calculations for how many digits to drop from the input. +% \begin{macrocode} +\cs_new:Npn \@@_round_places:nNnnnNn #1#2#3#4#5#6#7 + { + \tl_if_blank:nTF {#5} + { + \int_compare:nNnTF \l_@@_round_precision_int > 0 + { \@@_round_places_decimal:nNnnNn } + { \@@_round_places_integer:nNnnNn } + {#1} #2 {#3} {#4} #6 {#7} + } + { \exp_not:n { {#1} #2 {#3} {#4} {#5} #6 {#7} } } + } +\cs_new:Npn \@@_round_places_decimal:nNnnNn #1#2#3#4#5#6 + { } +\cs_new:Npn \@@_round_places_integer:nNnnNn #1#2#3#4#5#6 + { } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}[EXP]{\@@_round_uncertainty:nNnnnNn} +% \begin{macrocode} +\cs_new:Npn \@@_round_uncertainty:nNnnnNn #1#2#3#4#5#6#7 + { + \tl_if_blank:nTF {#5} + { \exp_not:n { {#1} #2 {#3} {#4} { } #6 {#7} } } + { } + } +% \end{macrocode} +% \end{macro} +% +% \subsection{Formatting parsed numbers} +% +% \begin{variable} +% { +% \l_@@_bracket_negative_bool , +% \l_@@_bracket_close_tl , +% \l_@@_explicit_plus_bool , +% \l_@@_exponent_base_tl , +% \l_@@_exponent_product_tl , +% \l_@@_group_decimal_bool , +% \l_@@_group_integer_bool , +% \l_@@_group_minimum_int , +% \l_@@_group_separator_tl , +% \l_@@_negative_color_tl , +% \l_@@_bracket_open_tl , +% \l_@@_output_uncert_close_tl , +% \l_@@_output_complex_tl , +% \l_@@_output_decimal_tl , +% \l_@@_output_uncert_open_tl , +% \l_@@_uncert_separate_bool , +% \l_@@_tight_bool , +% \l_@@_unity_mantissa_bool , +% \l_@@_zero_exponent_bool +% } +% Keys producing tokens in the output. +% \begin{macrocode} +\keys_define:nn { siunitx } + { + bracket-negative .bool_set:N = + \l_@@_bracket_negative_bool , + explicit-plus .bool_set:N = + \l_@@_explicit_plus_bool , + exponent-base .tl_set:N = + \l_@@_exponent_base_tl , + exponent-product .tl_set:N = + \l_@@_exponent_product_tl , + group-digits .choice: , + group-digits / all .code:n = + { + \bool_set_true:N \l_@@_group_decimal_bool + \bool_set_true:N \l_@@_group_integer_bool + } , + group-digits / decimal .code:n = + { + \bool_set_true: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 / none .code:n = + { + \bool_set_false:N \l_@@_group_decimal_bool + \bool_set_false:N \l_@@_group_integer_bool + } , + group-digits .default:n = all , + group-minimum-digits .int_set:N = + \l_@@_group_minimum_int , + group-separator .tl_set:N = + \l_@@_group_separator_tl , + negative-color .tl_set:N = + \l_@@_negative_color_tl , + number-close-bracket .tl_set:N = + \l_@@_bracket_close_tl , + number-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 .tl_set:N = + \l_@@_output_decimal_tl , + output-open-uncertainty .tl_set:N = + \l_@@_output_uncert_open_tl , + separate-uncertainty .bool_set:N = + \l_@@_uncert_separate_bool , + tight-spacing .bool_set:N = + \l_@@_tight_bool , + unity-mantissa .bool_set:N = + \l_@@_unity_mantissa_bool , + zero-exponent .bool_set:N = + \l_@@_zero_exponent_bool , + } +\bool_new:N \l_@@_group_decimal_bool +\bool_new:N \l_@@_group_integer_bool +% \end{macrocode} +% \end{variable} +% +% \begin{macro}{\@@_format:} +% \begin{macrocode} +\cs_new_protected:Npn \@@_format: + { + \tl_set:Nx \l_@@_formatted_tl + { + \tl_if_empty:NTF \l_@@_real_tl + { + \tl_if_empty:NF \l_@@_imaginary_tl + { \@@_format:N \l_@@_imaginary_tl } + } + { + \tl_if_empty:NTF \l_@@_imaginary_tl + { \@@_format:N \l_@@_real_tl } + { ??? } + } + } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[EXP]{\@@_format:N} +% \begin{macro}[EXP]{\@@_format:nNnnnNn} +% \begin{macro}[EXP]{\@@_format_comparator:n} +% \begin{macro}[EXP]{\@@_format_sign:N, \@@_format_sign_aux:N} +% \begin{macro}[EXP] +% {\@@_format_sign_color:w, \@@_format_sign_brackets:w} +% \begin{macro}[EXP]{\@@_format_integer:nnn} +% \begin{macro}[EXP]{\@@_format_decimal:n, \@@_format_decimal:f} +% \begin{macro}[EXP]{\@@_format_digits:nn} +% \begin{macro}[EXP]{\@@_format_integer_aux:n} +% \begin{macro}[EXP] +% { +% \@@_format_integer_aux_0:n, +% \@@_format_integer_aux_1:n, +% \@@_format_integer_aux_2:n +% } +% \begin{macro}[EXP]{\@@_format_decimal_aux:n} +% \begin{macro}[EXP]{\@@_format_decimal_loop:NNNN} +% \begin{macro}[EXP]{\@@_format_integer_first:nnNN} +% \begin{macro}[EXP]{\@@_format_integer_loop:NNNN} +% \begin{macro}[EXP]{\@@_format_uncertainty:nn} +% \begin{macro}[EXP]{\@@_format_uncertainty_unaligned:} +% \begin{macro}[EXP] +% {\@@_format_uncertainty_aux:nn, \@@_format_uncertainty_aux:fn} +% \begin{macro}[EXP] +% {\@@_format_uncertainty:nnw, \@@_format_uncertainty:fnw} +% \begin{macro}[EXP]{\@@_format_uncertainty:nw} +% \begin{macro}[EXP]{\@@_format_exponent:Nnn} +% \begin{macro}[EXP]{\@@_format_end:} +% The approach to formatting a single number is to split into +% the constituent parts. All of the parts are assembled including +% inserting tabular alignment markers (which may be empty) for each +% separate unit. +% \begin{macrocode} +\cs_new:Npn \@@_format:N #1 + { \exp_after:wN \@@_format:nNnnnNn #1 } +\cs_new:Npn \@@_format:nNnnnNn #1#2#3#4#5#6#7 + { + \@@_format_comparator:n {#1} + \@@_format_sign:N #2 + \@@_format_integer:nnn {#3} {#4} {#7} + \@@_format_decimal:n {#4} + \@@_format_uncertainty:nn {#5} {#4} + \@@_format_exponent:Nnn #6 {#7} { #3 . #4 } + \@@_format_end: + } +% \end{macrocode} +% To get the spacing correct this needs to be an ordinary math character. +% \begin{macrocode} +\cs_new:Npn \@@_format_comparator:n #1 + { + \tl_if_blank:nF {#1} + { \exp_not:n { \mathord {#1} } } + \exp_not:V \l_@@_tab_tl + } +% \end{macrocode} +% Formatting signs has to deal with some additional formatting requirements +% for negative numbers. Both making such numbers a fixed color and bracketing +% them needs some rearrangement of the order of tokens, which is set up in +% the main formatting macro by the dedicated do-nothing end function. +% \begin{macrocode} +\cs_new:Npn \@@_format_sign:N #1 + { + \str_if_eq:nnTF {#1} { + } + { + \bool_if:NT \l_@@_explicit_plus_bool + { \@@_format_sign_aux:N #1 } + } + { + \str_if_eq:nnTF {#1} { - } + { + \tl_if_empty:NF \l_@@_negative_color_tl + { \@@_format_sign_color:w } + \bool_if:NTF \l_@@_bracket_negative_bool + { \@@_format_sign_brackets:w } + { \@@_format_sign_aux:N #1 } + } + { \@@_format_sign_aux:N #1 } + } + } +\cs_new:Npn \@@_format_sign_aux:N #1 + { + \bool_if:NTF \l_@@_tight_bool + { \exp_not:n { \mathord {#1} } } + { \exp_not:n {#1} } + } +\cs_new:Npn + \@@_format_sign_color:w #1 \@@_format_end: + { + \exp_not:N \textcolor { \exp_not:V \l_@@_negative_color_tl } + { + #1 + \@@_format_end: + } + } +\cs_new:Npn + \@@_format_sign_brackets:w #1 \@@_format_end: + { + \exp_not:V \l_@@_bracket_open_tl + #1 + \exp_not:V \l_@@_bracket_close_tl + \@@_format_end: + } +% \end{macrocode} +% Digit formatting leads off with separate functions to allow for a few +% \enquote{up front} items before using a common set of tests for some common +% cases. The code then splits again as the two types of grouping need +% different strategies. +% \begin{macrocode} +\cs_new:Npn \@@_format_integer:nnn #1#2#3 + { + \bool_lazy_all:nF + { + { \str_if_eq_p:nn {#1} { 1 } } + { \tl_if_blank_p:n {#2} } + { ! \str_if_eq_p:nn {#3} { 0 } } + { ! \l_@@_unity_mantissa_bool } + } + { \@@_format_digits:nn { integer } {#1} } + } +\cs_new:Npn \@@_format_decimal:n #1 + { + \exp_not:V \l_@@_tab_tl + \tl_if_blank:nF {#1} + { \exp_not:V \l_@@_output_decimal_tl } + \exp_not:V \l_@@_tab_tl + \@@_format_digits:nn { decimal } {#1} + } +\cs_generate_variant:Nn \@@_format_decimal:n { f } +\cs_new:Npn \@@_format_digits:nn #1#2 + { + \bool_if:cTF { l_@@_group_ #1 _ bool } + { + \int_compare:nNnTF + { \tl_count:n {#2} } < \l_@@_group_minimum_int + { \exp_not:n {#2} } + { \use:c { @@_format_ #1 _aux:n } {#2} } + } + { \exp_not:n {#2} } + } +% \end{macrocode} +% For integers, we need to know how many digits there are to allow for the +% correct insertion of separators. That is done using a two-part set up such +% that there is no separator on the first pass. +% \begin{macrocode} +\cs_new:Npn \@@_format_integer_aux:n #1 + { + \use:c + { + @@_format_integer_aux_ + \int_eval:n { \int_mod:nn { \tl_count:n {#1} } { 3 } } + :n + } {#1} + } +\cs_new:cpn { @@_format_integer_aux_0:n } #1 + { \@@_format_integer_first:nnNN #1 \q_nil } +\cs_new:cpn { @@_format_integer_aux_1:n } #1 + { \@@_format_integer_first:nnNN { } { } #1 \q_nil } +\cs_new:cpn { @@_format_integer_aux_2:n } #1 + { \@@_format_integer_first:nnNN { } #1 \q_nil } +\cs_new:Npn \@@_format_integer_first:nnNN #1#2#3#4 + { + \exp_not:n {#1#2#3} + \quark_if_nil:NF #4 + { \@@_format_integer_loop:NNNN #4 } + } +\cs_new:Npn \@@_format_integer_loop:NNNN #1#2#3#4 + { + \exp_not:V \l_@@_group_separator_tl + \exp_not:n {#1#2#3} + \quark_if_nil:NF #4 + { \@@_format_integer_loop:NNNN #4 } + } +% \end{macrocode} +% For decimals, no need to do any counting, just loop using enough markers to +% find the end of the list. By passing the decimal marker, it is possible not +% to have to use a check on the content of the rest of the number. The +% |\use_none:n(n)| mop up the remaining |\q_nil| tokens. +% \begin{macrocode} +\cs_new:Npn \@@_format_decimal_aux:n #1 + { + \@@_format_decimal_loop:NNNN \c_empty_tl + #1 \q_nil \q_nil \q_nil + } +\cs_new:Npn \@@_format_decimal_loop:NNNN #1#2#3#4 + { + \quark_if_nil:NF #2 + { + \exp_not:V #1 + \exp_not:n {#2} + \quark_if_nil:NTF #3 + { \use_none:n } + { + \exp_not:n {#3} + \quark_if_nil:NTF #4 + { \use_none:nn } + { + \exp_not:n {#4} + \@@_format_decimal_loop:NNNN + \l_@@_group_separator_tl + } + } + } + } +% \end{macrocode} +% Uncertainties which are directly attached are easy to deal with. For those +% that are separated, the first step is to find if they are entirely +% contained within the decimal part, and to pad if they are. For the case +% where the boundary is crossed to the integer part, the correct number of +% digit tokens need to be removed from the start of the uncertainty and +% the split result sent to the appropriate auxiliaries. +% \begin{macrocode} +\cs_new:Npn \@@_format_uncertainty:nn #1#2 + { + \tl_if_blank:nTF {#1} + { \@@_format_uncertainty_unaligned: } + { + \bool_if:NTF \l_@@_uncert_separate_bool + { + \exp_not:V \l_@@_tab_tl + \@@_format_sign_aux:N \pm + \exp_not:V \l_@@_tab_tl + \@@_format_uncertainty_aux:fn + { \int_eval:n { \tl_count:n {#1} - \tl_count:n {#2} } } + {#1} + } + { + \exp_not:V \l_@@_output_uncert_open_tl + \exp_not:n {#1} + \exp_not:V \l_@@_output_uncert_close_tl + \@@_format_uncertainty_unaligned: + } + } + } +\cs_new:Npn \@@_format_uncertainty_unaligned: + { + \exp_not:V \l_@@_tab_tl + \exp_not:V \l_@@_tab_tl + \exp_not:V \l_@@_tab_tl + \exp_not:V \l_@@_tab_tl + } +\cs_new:Npn \@@_format_uncertainty_aux:nn #1#2 + { + \int_compare:nNnTF {#1} > 0 + { + \@@_format_uncertainty_aux:fnw + { \int_eval:n { #1 - 1 } } + { } + #2 \q_nil + } + { + 0 + \@@_format_decimal:f + { + \prg_replicate:nn { \int_abs:n {#1} } { 0 } + #2 + } + } + } +\cs_generate_variant:Nn \@@_format_uncertainty_aux:nn { f } +\cs_new:Npn \@@_format_uncertainty_aux:nnw #1#2#3 + { + \quark_if_nil:NF #3 + { + \int_compare:nNnTF {#1} = 0 + { \@@_format_uncertainty_aux:nw {#2#3} } + { + \@@_format_uncertainty_aux:fnw + { \int_eval:n { #1 - 1 } } + {#2#3} + } + } + } +\cs_generate_variant:Nn \@@_format_uncertainty_aux:nnw { f } +\cs_new:Npn \@@_format_uncertainty_aux:nw #1#2 \q_nil + { + \@@_format_digits:nn { integer } {#1} + \@@_format_decimal:n {#2} + } +% \end{macrocode} +% Setting the exponent part requires some information about the mantissa: +% was it there or not. This means that whilst only the sign and value for +% the exponent are typeset here, there is a need to also have access to the +% combined mantissa part (with a decimal marker). The rest of the work is +% about picking up the various options and getting the combinations right. +% For signs, the auxiliary from the main sign routine can be used, but not +% the main function: negative exponents don't have special handling. +% \begin{macrocode} +\cs_new:Npn \@@_format_exponent:Nnn #1#2#3 + { + \exp_not:V \l_@@_tab_tl + \bool_lazy_or:nnTF + { \l_@@_zero_exponent_bool } + { ! \str_if_eq_p:nn {#2} { 0 } } + { + \bool_lazy_and:nnTF + { \str_if_eq_p:nn {#3} { 1. } } + { ! \l_@@_unity_mantissa_bool } + { \exp_not:V \l_@@_tab_tl } + { + \bool_if:NTF \l_@@_tight_bool + { + \exp_not:N \mathord + { \exp_not:V \l_@@_exponent_product_tl } + } + { \exp_not:V \l_@@_exponent_product_tl } + \exp_not:V \l_@@_tab_tl + } + \exp_not:V \l_@@_exponent_base_tl + ^ + { + \bool_lazy_or:nnT + { \l_@@_explicit_plus_bool } + { ! \str_if_eq_p:nn {#1} { + } } + { \@@_format_sign_aux:N #1 } + \@@_format_digits:nn { integer } {#2} + } + } + { \exp_not:V \l_@@_tab_tl } + } +% \end{macrocode} +% A do-nothing marker used to allow shuffling of the output and so expandable +% operations for formatting. +% \begin{macrocode} +\cs_new:Npn \@@_format_end: { } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \subsection{Miscellaneous tools} +% +% \begin{variable}{\l_@@_valid_tl} +% The list of valid tokens. +% \begin{macrocode} +\tl_new:N \l_@@_valid_tl +% \end{macrocode} +% \end{variable} +% +% \begin{macro}[TF]{\siunitx_if_number:n} +% Test if an entire number is valid: this means parsing the number but not +% returning anything. +% \begin{macrocode} +\prg_new_protected_conditional:Npnn \siunitx_if_number:n #1 + { T , F , TF } + { + \group_begin: + \bool_set_true:N \l_@@_validate_bool + \@@_parse:n {#1} + \bool_lazy_and:nnTF + { \tl_if_empty_p:N \l_@@_real_tl } + { \tl_if_empty_p:N \l_@@_imaginary_tl } + { + \group_end: + \prg_return_false: + } + { + \group_end: + \prg_return_true: + } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[TF]{\siunitx_if_number_token:N} +% A simple conditional to answer the question of whether a specific token is +% possibly valid in a number. +% \begin{macrocode} +\prg_new_protected_conditional:Npnn \siunitx_if_number_token:N #1 + { T , F , TF } + { + \tl_set:Nx \l_@@_valid_tl + { + \exp_not:V \l_@@_input_uncert_close_tl + \exp_not:V \l_@@_input_complex_tl + \exp_not:V \l_@@_input_comparator_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_uncert_open_tl + \exp_not:V \l_@@_input_sign_tl + \exp_not:V \l_@@_input_uncert_sign_tl + } + \tl_if_in:VnTF \l_@@_valid_tl {#1} + { \prg_return_true: } + { \prg_return_false: } + } +% \end{macrocode} +% \end{macro} +% +% \subsection{Messages} +% +% \begin{macrocode} +\msg_new:nnnn { siunitx } { number / invalid-input } + { Invalid~number~'#1'. } + { + The~input~'#1'~could~not~be~parsed~as~a~number~following~the~ + format~defined~in~module~documentation. + } +% \end{macrocode} +% +% \subsection{Standard settings for module options} +% +% Some of these follow naturally from the point of definition +% (\emph{e.g.}~boolean variables are always |false| to begin with), +% but for clarity everything is set here. +% \begin{macrocode} +\keys_set:nn { siunitx } + { + bracket-negative = false , + evaluate-expression = false , + explicit-plus = false , + exponent-base = 10 , + exponent-product = \times , + expression = #1 , + group-digits = all , + group-minimum-digits = 4 , + group-separator = \, , % ( + 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-ignore = \, , + input-open-uncertainty = ( , % ) + input-signs = +-\mp\pm , + input-uncertainty-signs = \pm , + negative-color = , % ( + number-close-bracket = ) , + number-open-bracket = ( , % ) + output-close-uncertainty = ) , + output-complex-root = \mathrm { i } , + output-decimal-marker = . , + output-open-uncertainty = ( , % ) + round-half = up , + round-minimum = 0 , + round-mode = none , + round-precision = 2 , + separate-uncertainty = false , + tight-spacing = false , + unity-mantissa = false , + zero-exponent = false + } +% \end{macrocode} +% +% \begin{macrocode} +%</package> +% \end{macrocode} +% +% \end{implementation} +% +% \PrintIndex diff --git a/Master/texmf-dist/source/latex/siunitx/siunitx-print.dtx b/Master/texmf-dist/source/latex/siunitx/siunitx-print.dtx new file mode 100644 index 00000000000..98c6ee03609 --- /dev/null +++ b/Master/texmf-dist/source/latex/siunitx/siunitx-print.dtx @@ -0,0 +1,767 @@ +% \iffalse meta-comment +% +% File: siunitx-print.dtx Copyright (C) 2016-2017 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 +% +% https://www.latex-project.org/lppl.txt +% +% This file is part of the "siunitx bundle" (The Work in LPPL) +% and all files in that bundle must be distributed together. +% +% The released version of this bundle is available from CTAN. +% +% ----------------------------------------------------------------------- +% +% The development version of the bundle can be found at +% +% https://github.com/josephwright/siunitx +% +% for those people who are interested. +% +% ----------------------------------------------------------------------- +% +%<*driver> +\documentclass{l3doc} +% The next line is needed so that \GetFileInfo will be able to pick up +% version data +\usepackage{siunitx} +\begin{document} + \DocInput{\jobname.dtx} +\end{document} +%</driver> +% \fi +% +% \GetFileInfo{siunitx.sty} +% +% \title{^^A +% \pkg{siunitx-print} -- Printing material with font control^^A +% \thanks{This file describes \fileversion, +% last revised \filedate.}^^A +% } +% +% \author{^^A +% Joseph Wright^^A +% \thanks{^^A +% E-mail: +% \href{mailto:joseph.wright@morningstar2.co.uk} +% {joseph.wright@morningstar2.co.uk}^^A +% }^^A +% } +% +% \date{Released \filedate} +% +% \maketitle +% +% \begin{documentation} +% +% This submodule is focussed on providing controlled printing for numbers and +% units. Key to this is control of font: conventions for printing quantities +% mean that the exact nature of the output is important. At the same time, this +% module provides flexibility for the user in terms of which aspects of the font +% are responsive to the surrounding general text. Printing material may also +% take place in text or math mode. +% +% The printing routines assume that normal \LaTeXe{} font selection commands +% are available, in particular \cs{bfsries}, \cs{mathrm}, \cs{mathversion}, +% \cs{mdseries}, \cs{rmfamily} and \cs{upshape}. It also requires the standard +% \LaTeXe{} kernel commands \cs{ensuremath}, \cs{textsubscript} and +% \cs{textsuperscript} for printing in text mode. The following packages are +% also required to provide the functionality detailed. +% \begin{itemize} +% \item \pkg{color}: support for color using \cs{textcolor} +% \item \pkg{textcomp}: \cs{textminus} and \cs{textpm} for printing +% in text mode +% \item \pkg{amstext}: the \cs{text} command for printing in text mode +% \end{itemize} +% +% \begin{function}{\siunitx_print:nn, \siunitx_print:nV} +% \begin{syntax} +% \cs{siunitx_print:nn} \Arg{type} \Arg{material} +% \end{syntax} +% Prints the \meta{material} according the the prevailing settings for the +% submodule as applicable to the \meta{type} of content: the latter should be +% either |number| or |unit|. The \meta{material} should comprise normal +% \LaTeX{} mark-up for numbers or units. In particular, units will typically +% use |\mathrm| to indicate material to be printed in the current upright +% roman font, and |^| and |_| will typically be used to indicate super- and +% subscripts, respectively. These elements will be correctly handled when +% printing for example using |\mathsf| in math mode, or using only text +% fonts. +% \end{function} +% +% \begin{variable}{\l_siunitx_print_series_prop} +% This properly list contains mappings from text mode font weights to math +% mode font versions. The standard settings here cover +% \begin{itemize} +% \item[\texttt{m}] Standard (mid) weight, mapping to math version +% |normal|. +% \item[\texttt{bx}] Bold exanded weight, mapping to math version |bold|. +% \item[\texttt{lt}] Light weight, mapping to math version |light|. +% \item[\texttt{l}] Light weight, mapping to math version |light|. +% \end{itemize} +% \end{variable} +% +% \subsection{Key--value options} +% +% The options defined by this submodule are available within the \pkg{l3keys} +% |siunitx| tree. +% +% \begin{function}{color} +% \begin{syntax} +% |color| = \meta{color} +% \end{syntax} +% Color to apply to printed output: the latter should be a named color +% defined for use with \cs{textcolor}. The standard setting is empty (no +% color). +% \end{function} +% +% \begin{function}{mode} +% \begin{syntax} +% |mode| = \meta{choice} +% \end{syntax} +% Selects which mode (math or text) the output is printed in: a choice +% from the options |match|, |math| or |text|. The option |match| matches +% the mode prevailing at the point \cs{siunitx_print:nn} is called. The +% |math| and |text| options choose the relevant \TeX{} mode for printing. +% The standard setting is |math|. +% \end{function} +% +% \begin{function}{number-color} +% \begin{syntax} +% |number-color| = \meta{color} +% \end{syntax} +% Color to apply to numbers in output: the latter should be a named color +% defined for use with \cs{textcolor}. The standard setting is empty (no +% color). +% \end{function} +% +% \begin{function}{number-mode} +% \begin{syntax} +% |number-mode| = \meta{choice} +% \end{syntax} +% Selects which mode (math or text) the numbers are printed in: a choice +% from the options |match|, |math| or |text|. The option |match| matches +% the mode prevailing at the point \cs{siunitx_print:nn} is called. The +% |math| and |text| options choose the relevant \TeX{} mode for printing. +% The standard setting is |math|. +% \end{function} +% +% \begin{function}{propagate-math-font} +% \begin{syntax} +% |propagate-math-font| = |true|\verb"|"|false| +% \end{syntax} +% Switch to determine if the currently-active math font is applied within +% printed output. This is relevant only when \cs{siunitx_print:nn} is +% called from within math mode: in text mode there is not active math +% font. When not active, math mode material will be typeset using +% standard math mode fonts without any changes being made to the +% supplied argument. The standard setting is |false|. +% \end{function} +% +% \begin{function}{reset-math-version} +% \begin{syntax} +% |reset-math-version| = |true|\verb"|"|false| +% \end{syntax} +% Switch to determine whether the active \cs{mathversion} is reset to +% |normal| when printing in math mode. Note that math version is typically +% used to select \cs{boldmath}, though it is also be used by +% \foreign{e.g.}~\pkg{sansmath}. The standard setting is |true|. +% \end{function} +% +% \begin{function}{reset-text-family} +% \begin{syntax} +% |reset-text-family| = |true|\verb"|"|false| +% \end{syntax} +% Switch to determine whether the active math family is reset to +% \cs{rmfamily} when printing in text mode. The standard setting is |true|. +% \end{function} +% +% \begin{function}{reset-text-series} +% \begin{syntax} +% |reset-text-series| = |true|\verb"|"|false| +% \end{syntax} +% Switch to determine whether the active math series is reset to +% \cs{mdseries} when printing in text mode. The standard setting is |true|. +% \end{function} +% +% \begin{function}{reset-text-shape} +% \begin{syntax} +% |reset-text-shape| = |true|\verb"|"|false| +% \end{syntax} +% Switch to determine whether the active math shape is reset to +% \cs{upshape} when printing in text mode. The standard setting is |true|. +% \end{function} +% +% \begin{function}{text-family-to-math} +% \begin{syntax} +% |text-family-to-math| = |true|\verb"|"|false| +% \end{syntax} +% Switch to determine if the family of the current text font should be +% applied (where possible) to printing in math mode. The standard setting is +% |false|. +% \end{function} +% +% \begin{function}{text-weight-to-math} +% \begin{syntax} +% |text-weight-to-math| = |true|\verb"|"|false| +% \end{syntax} +% Switch to determine if the weight of the current text font should be +% applied (where possible) to printing in math mode. This is achieved by +% setting the \cs{mathversion}, and so will override |reset-math-version|. +% The mappings between text and math weight are stored in +% \cs{l_siunitx_print_series_prop}. The standard setting is |false|. +% \end{function} +% +% \begin{function}{unit-color} +% \begin{syntax} +% |unit-color| = \meta{color} +% \end{syntax} +% Color to apply to units in output: the latter should be a named color +% defined for use with \cs{textcolor}. The standard setting is empty (no +% color). +% \end{function} +% +% \begin{function}{unit-mode} +% \begin{syntax} +% |unit-mode| = \meta{choice} +% \end{syntax} +% Selects which mode (math or text) units are printed in: a choice +% from the options |match|, |math| or |text|. The option |match| matches +% the mode prevailing at the point \cs{siunitx_print:nn} is called. The +% |math| and |text| options choose the relevant \TeX{} mode for printing. +% The standard setting is |math|. +% \end{function} +% +% \end{documentation} +% +% \begin{implementation} +% +% \section{\pkg{siunitx-print} implementation} +% +% Start the \pkg{DocStrip} guards. +% \begin{macrocode} +%<*package> +% \end{macrocode} +% +% Identify the internal prefix (\LaTeX3 \pkg{DocStrip} convention): only +% internal material in this \emph{submodule} should be used directly. +% \begin{macrocode} +%<@@=siunitx_print> +% \end{macrocode} +% +% \subsection{Initial set up} +% +% The printing routines depend on \pkg{amstext} for text mode working. +% \begin{macrocode} +\RequirePackage { amstext } +% \end{macrocode} +% +% Color support is always required. +% \begin{macrocode} +\RequirePackage { color } +% \end{macrocode} +% +% For a sensible \cs{textminus} we load \pkg{textcomp} if \pkg{fontspec} +% is not in use. +% \begin{macrocode} +\AtBeginDocument + { + \@ifpackageloaded { fontspec } + { } + { \RequirePackage { textcomp } } + } +% \end{macrocode} +% +% \begin{variable}{\l_@@_tmp_box} +% Scratch space. +% \begin{macrocode} +\box_new:N \l_@@_tmp_box +% \end{macrocode} +% \end{variable} +% +% \begin{macro}{\document} +% \begin{macro}{\@@_store_fam:n} +% \begin{variable}{\c_@@_mathrm_int, \c_@@_mathsf_int, \c_@@_mathtt_int} +% In order to test math fonts, we need information about the \cs{fam} used +% by the various options. This is run as a hook onto \cs{document}, rather +% than using \tn{AtBeginDocument} as it has to come after anything that +% \pkg{fontspec} does (nasty errors arise otherwise). As this is a true +% one-off, we avoid wasting a box. +% \begin{macrocode} +\tl_put_right:Nn \document + { + \@@_store_fam:n { rm } + \@@_store_fam:n { sf } + \@@_store_fam:n { tt } + \ignorespaces + } +\cs_new_protected:Npn \@@_store_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: + } +% \end{macrocode} +% \end{variable} +% \end{macro} +% \end{macro} +% +% \subsection{Printing routines} +% +% \begin{variable} +% { +% \l_@@_number_color_tl , +% \l_@@_number_mode_tl , +% \l_@@_unit_color_tl , +% \l_@@_unit_mode_tl , +% \l_@@_math_font_bool , +% \l_@@_math_version_bool , +% \l_@@_math_family_bool , +% \l_@@_math_weight_bool , +% \l_@@_text_family_tl , +% \l_@@_text_series_tl , +% \l_@@_text_shape_tl +% } +% Options which apply to the main formatting routine, and so are not tied +% to either symbolic or literal input. +% \begin{macrocode} +\tl_new:N \l_@@_number_mode_tl +\tl_new:N \l_@@_unit_mode_tl +\keys_define:nn { siunitx } + { + color .meta:n = + { number-color = #1 , unit-color = #1 } , + mode .meta:n = + { number-mode = #1 , unit-mode = #1 } , + number-color .tl_set:N = + \l_@@_number_color_tl , + number-mode .choices:nn = + { match , math , text } + { + \tl_set_eq:NN + \l_@@_number_mode_tl \l_keys_choice_tl + } , + propagate-math-font .bool_set:N = + \l_@@_math_font_bool , + reset-math-version .bool_set:N = + \l_@@_math_version_bool , + reset-text-family .bool_set:N = + \l_@@_text_family_bool , + reset-text-series .bool_set:N = + \l_@@_text_series_bool , + reset-text-shape .bool_set:N = + \l_@@_text_shape_bool , + text-family-to-math .bool_set:N = + \l_@@_math_family_bool , + text-weight-to-math .bool_set:N = + \l_@@_math_weight_bool , + unit-color .tl_set:N = + \l_@@_unit_color_tl , + unit-mode .choices:nn = + { match , math , text } + { + \tl_set_eq:NN + \l_@@_unit_mode_tl \l_keys_choice_tl + } + } +% \end{macrocode} +% \end{variable} +% +% \begin{macro}{\siunitx_print:nn, \siunitx_print:nV} +% The main printing function doesn't actually need to do very much: just set +% the color and select the correct sub-function. +% \begin{macrocode} +\cs_new_protected:Npn \siunitx_print:nn #1#2 + { + \tl_if_empty:cTF { l_@@_ #1 _color_tl } + { \use:n } + { \exp_args:Nv \textcolor { l_@@_ #1 _color_tl } } + { + \use:c + { + @@_ + \tl_use:c { l_@@_ #1 _mode_tl } :n + } + {#2} + } + } +\cs_generate_variant:Nn \siunitx_print:nn { nV } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_match:n} +% When the \emph{output} mode should match the input, a simple selection of +% route can be made. +% \begin{macrocode} +\cs_new_protected:Npn \@@_match:n #1 + { + \mode_if_math:TF + { \@@_math:n {#1} } + { \@@_text:n {#1} } + } +% \end{macrocode} +% \end{macro} +% +% \begin{variable}{\l_siunitx_print_series_prop} +% Mapping data to relate text series to math version. +% \begin{macrocode} +\prop_new:N \l_siunitx_print_series_prop +\prop_put:Nnn \l_siunitx_print_series_prop { m } { normal } +\prop_put:Nnn \l_siunitx_print_series_prop { bx } { bold } +\prop_put:Nnn \l_siunitx_print_series_prop { l } { light } +\prop_put:Nnn \l_siunitx_print_series_prop { lt } { light } +% \end{macrocode} +% \end{variable} +% +% \begin{macro}{\@@_math:n} +% \begin{macro}{\@@_math_version:nn, \@@_math_version:Vn} +% \begin{macro} +% { +% \@@_math_auxi:n, +% \@@_math_auxii:n, +% \@@_math_auxiii:n, +% \@@_math_auxiv:n, +% \@@_math_auxv:n +% } +% \begin{macro}{\@@_math_aux:Nn, \@@_math_aux:cn} +% \begin{macro}{\@@_math_sub:n, \@@_math_super:n, \@@_math_script:n} +% \begin{macro}{\@@_math_text:n} +% The first step in setting in math mode is to check on the math version. +% The starting point is the question of whether text series needs to +% propagate to math mode: if so, check on the mapping, otherwise check on +% the current math version. +% \begin{macrocode} +\cs_new_protected:Npn \@@_math:n #1 + { + \bool_if:NTF \l_@@_math_weight_bool + { + \prop_get:NVNTF \l_siunitx_print_series_prop + \f@series \l_@@_tmp_tl + { \@@_math_version:Vn \l_@@_tmp_tl {#1} } + { \@@_math_auxi:n {#1} } + } + { \@@_math_auxi:n {#1} } + } +\cs_new_protected:Npn \@@_math_auxi:n #1 + { + \bool_if:NTF \l_@@_math_version_bool + { \@@_math_version:nn { normal } {#1} } + { \@@_math_auxii:n {#1} } + } +% \end{macrocode} +% Any setting which changes the math version can only be set from text mode +% (as it applies at the level of a formula). As such, the first test is to +% see if that needs to be to check if the math version has to be set: if so, +% switch to text mode, sort it out and switch back. That of course means +% that in such cases, line breaking will not be possible. +% \begin{macrocode} +\cs_new_protected:Npn \@@_math_version:nn #1#2 + { + \str_if_eq_x:nnTF { \math@version } { #1 } + { \@@_math_auxii:n {#2} } + { + \mode_if_math:TF + { \text } + { \use:n } + { + \mathversion {#1} + \@@_math_auxii:n {#2} + } + } + } +\cs_generate_variant:Nn \@@_math_version:nn { V } +% \end{macrocode} +% At this point, force math mode then start dealing with setting math font +% based on text family. If the text family is roman, life is slightly +% different to if it is sanserif or monospaced. In all cases, the outcomes +% can be handled using the same routines as for normal math mode treatment. +% \begin{macrocode} +\cs_new_protected:Npn \@@_math_auxii:n #1 + { \ensuremath { \@@_math_auxiii:n {#1} } } +\cs_new_protected:Npn \@@_math_auxiii:n #1 + { + \bool_if:NTF \l_@@_math_family_bool + { + \str_case_x:nnF { \f@family } + { + { \rmdefault } { \@@_math_auxv:n } + { \sfdefault } { \@@_math_aux:Nn \mathsf } + { \ttdefault } { \@@_math_aux:Nn \mathtt } + } + { \@@_math_auxiv:n } + } + { \@@_math_auxiv:n } + {#1} + } +% \end{macrocode} +% Now we deal with the font selection in math mode. There are two possible +% cases. First, we are retaining the current math font, and the active one is +% \cs{mathsf} or \cs{mathtt}: that needs to be applied to the argument. +% Alternatively, if the current font is not retained, ensure that +% normal math mode rules are active. The parts here are split up to allow +% reuse when picking up the text family. +% \begin{macrocode} +\cs_new_protected:Npn \@@_math_auxiv:n #1 + { + \bool_if:NTF \l_@@_math_font_bool + { + \int_case:nnF \fam + { + \c_@@_mathsf_int { \@@_math_aux:Nn \mathsf } + \c_@@_mathtt_int { \@@_math_aux:Nn \mathtt } + } + { \use:n } + } + { \@@_math_auxv:n } + {#1} + } +\cs_new_protected:Npn \@@_math_auxv:n #1 + { + \bool_lazy_or:nnTF + { \int_compare_p:nNn \fam = { -1 } } + { \int_compare_p:nNn \fam = \c_@@_mathrm_int } + { \use:n } + { \mathrm } + {#1} + } +% \end{macrocode} +% Search-and-replace fun: deal with any \cs{mathrm} in the argument and +% also inside sub/superscripts. +% \begin{macrocode} +\cs_new_protected:Npx \@@_math_aux:Nn #1#2 + { + \group_begin: + \tl_set:Nn \exp_not:N \l_@@_tmp_tl {#2} + \tl_replace_all:Nnn \exp_not:N \l_@@_tmp_tl + { \exp_not:N \mathrm } { \exp_not:N \use:n } + \tl_replace_all:Nnn \exp_not:N \l_@@_tmp_tl + { \char_generate:nn { `\_ } { 8 } } + { \exp_not:N \@@_math_sub:n } + \tl_replace_all:Nnn \exp_not:N \l_@@_tmp_tl + { ^ } + { \exp_not:N \@@_math_super:n } + #1 { \exp_not:N \tl_use:N \exp_not:N \l_@@_tmp_tl } + \group_end: + } +\cs_generate_variant:Nn \@@_math_aux:Nn { c } +\cs_new_protected:Npx \@@_math_sub:n #1 + { + \char_generate:nn { `\_ } { 8 } + { \exp_not:N \@@_math_script:n {#1} } + } +\cs_new_protected:Npn \@@_math_super:n #1 + { ^ { \@@_math_script:n {#1} } } +\cs_new_protected:Npn \@@_math_script:n #1 + { + \group_begin: + \tl_set:Nn \l_@@_tmp_tl {#1} + \tl_replace_all:Nnn \l_@@_tmp_tl { \mathrm } { \use:n } + \tl_use:N \l_@@_tmp_tl + \group_end: + } +% \end{macrocode} +% To match the text mode font, there is a simple look-up of the current +% font family. Luckily, mappings to math mode equivalents are easy. +% \begin{macrocode} + +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@@_text:n} +% \begin{macro}{\@@_text_replace:n} +% \begin{macro}{\@@_text_replace:N} +% \begin{macro}{\@@_text_replace:NNn} +% \begin{macro}{\@@_text_sub:n, \@@_text_super:n} +% \begin{macro}{\@@_text_scripts:NnN} +% \begin{macro}{\@@_text_scripts:} +% \begin{macro}{\@@_text_scripts_one:NnN} +% \begin{macro}{\@@_text_scripts_two:NnNn} +% \begin{macro}{\@@_text_scripts_two:nn} +% \begin{macro}{\@@_text_scripts_two:n} +% Typesetting in text mode is easy in font control terms but more tricky +% in the manipulation of the input. The easy part comes first. +% \begin{macrocode} +\cs_new_protected:Npn \@@_text:n #1 + { + \text + { + \bool_if:NT \l_@@_text_family_bool + { \rmfamily } + \bool_if:NT \l_@@_text_series_bool + { \mdseries } + \bool_if:NT \l_@@_text_shape_bool + { \upshape } + \@@_text_replace:n {#1} + } + } +% \end{macrocode} +% To get math mode material to print in text mode, various search-and-replace +% steps are needed. The \cs{mathrm} command is also disabled as it is +% invalid in text mode. +% \begin{macrocode} +\cs_new_protected:Npn \@@_text_replace:n #1 + { + \group_begin: + \tl_set:Nn \l_@@_tmp_tl {#1} + \@@_text_replace:N \l_@@_tmp_tl + \tl_use:N \l_@@_tmp_tl + \group_end: + } +\cs_new_protected:Npx \@@_text_replace:N #1 + { + \exp_not:N \@@_text_replace:NNn #1 + \exp_not:N \mathrm + { \exp_not:N \use:n } + \exp_not:N \pm + { \exp_not:N \textpm } + \exp_not:N \mp + { \exp_not:n { \ensuremath { \mp } } } + - + { \exp_not:N \textminus } + \char_generate:nn { `\_ } { 8 } + { \exp_not:N \@@_text_sub:n } + ^ + { \exp_not:N \@@_text_super:n } + \exp_not:N \q_recursion_tail + { ? } + \exp_not:N \q_recursion_stop + } +\cs_new_protected:Npn \@@_text_replace:NNn #1#2#3 + { + \quark_if_recursion_tail_stop:N #2 + \tl_replace_all:Nnn #1 {#2} {#3} + \@@_text_replace:NNn #1 + } +% \end{macrocode} +% Sub- and superscripts can be in any order in the source. The first step +% of handling them is therefore to do a look-ahead to work out whether +% only one or both are present. +% \begin{macrocode} +\cs_new_protected:Npn \@@_text_sub:n #1 + { + \@@_text_scripts:NnN + \textsubscript {#1} \@@_text_super:n + } +\cs_new_protected:Npn \@@_text_super:n #1 + { + \@@_text_scripts:NnN + \textsuperscript {#1} \@@_text_sub:n + } +\cs_new_protected:Npn \@@_text_scripts:NnN #1#2#3 + { + \cs_set_protected:Npn \@@_text_scripts: + { + \if_meaning:w \l_peek_token #3 + \exp_after:wN \@@_text_scripts_two:NnNn + \else: + \exp_after:wN \@@_text_scripts_one:Nn + \fi: + #1 {#2} + } + \peek_after:Nw \@@_text_scripts: + } +\cs_new_protected:Npn \@@_text_scripts: { } +% \end{macrocode} +% In the simple case of one script item, we have to do a search-and-replace +% to deal with anything inside the argument. +% \begin{macrocode} +\cs_new_protected:Npn \@@_text_scripts_one:Nn #1#2 + { + \group_begin: + \tl_set:Nn \l_@@_tmp_tl {#2} + \@@_text_replace:N \l_@@_tmp_tl + \exp_args:NNV \group_end: + #1 \l_@@_tmp_tl + } +% \end{macrocode} +% For the two scripts case, we cannot use |\textsubscript|/|\textsuperscript| +% as they don't stack directly. Instead, we sort out the ordering then use +% an implementation for both parts that is the same as the kernel text +% scripts. +% \begin{macrocode} +\cs_new_protected:Npn \@@_text_scripts_two:NnNn #1#2#3#4 + { + \cs_if_eq:NNTF #1 \textsubscript + { \@@_text_scripts_two:nn {#4} {#2} } + { \@@_text_scripts_two:nn {#2} {#4} } + } +\cs_new_protected:Npx \@@_text_scripts_two:nn #1#2 + { + \group_begin: + \exp_not:N \m@th + \exp_not:N \ensuremath + { + ^ { \exp_not:N \@@_text_scripts_two:n {#1} } + \char_generate:nn { `\_ } { 8 } + { \exp_not:N \@@_text_scripts_two:n {#2} } + } + \group_end: + } +\cs_new_protected:Npn \@@_text_scripts_two:n #1 + { + \mbox + { + \fontsize \sf@size \z@ \selectfont + \@@_text_scripts_one:Nn \use:n {#1} + } + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \subsection{Standard settings for module options} +% +% Some of these follow naturally from the point of definition +% (\foreign{e.g.}~boolean variables are always |false| to begin with), +% but for clarity everything is set here. +% \begin{macrocode} +\keys_set:nn { siunitx } + { + color = , + mode = math , + number-color = , + number-mode = math , + propagate-math-font = false , + reset-math-version = true , + reset-text-shape = true , + reset-text-series = true , + reset-text-family = true , + text-family-to-math = false , + text-weight-to-math = false , + unit-color = , + unit-mode = math + } +% \end{macrocode} +% +% \begin{macrocode} +%</package> +% \end{macrocode} +% +% \end{implementation} +% +% \PrintIndex
\ No newline at end of file diff --git a/Master/texmf-dist/source/latex/siunitx/siunitx-table.dtx b/Master/texmf-dist/source/latex/siunitx/siunitx-table.dtx new file mode 100644 index 00000000000..1b22b33a469 --- /dev/null +++ b/Master/texmf-dist/source/latex/siunitx/siunitx-table.dtx @@ -0,0 +1,606 @@ +% \iffalse meta-comment +% +% File: siunitx-table.dtx Copyright (C) 2016-2017 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 +% +% https://www.latex-project.org/lppl.txt +% +% This file is part of the "siunitx bundle" (The Work in LPPL) +% and all files in that bundle must be distributed together. +% +% The released version of this bundle is available from CTAN. +% +% ----------------------------------------------------------------------- +% +% The development version of the bundle can be found at +% +% https://github.com/josephwright/siunitx +% +% for those people who are interested. +% +% ----------------------------------------------------------------------- +% +%<*driver> +\documentclass{l3doc} +% The next line is needed so that \GetFileInfo will be able to pick up +% version data +\usepackage{siunitx} +\begin{document} + \DocInput{\jobname.dtx} +\end{document} +%</driver> +% \fi +% +% \GetFileInfo{siunitx.sty} +% +% \title{^^A +% \pkg{siunitx-table} -- Formatting numbers in tables^^A +% \thanks{This file describes \fileversion, +% last revised \filedate.}^^A +% } +% +% \author{^^A +% Joseph Wright^^A +% \thanks{^^A +% E-mail: +% \href{mailto:joseph.wright@morningstar2.co.uk} +% {joseph.wright@morningstar2.co.uk}^^A +% }^^A +% } +% +% \date{Released \filedate} +% +% \maketitle +% +% \begin{documentation} +% +% \end{documentation} +% +% \begin{implementation} +% +% \section{\pkg{siunitx-table} implementation} +% +% Start the \pkg{DocStrip} guards. +% \begin{macrocode} +%<*package> +% \end{macrocode} +% +% Identify the internal prefix (\LaTeX3 \pkg{DocStrip} convention): only +% internal material in this \emph{submodule} should be used directly. +% \begin{macrocode} +%<@@=siunitx_table> +% \end{macrocode} +% +% \begin{variable}{\l_@@_tmp_tl} +% Scratch space. +% \begin{macrocode} +\tl_new:N \l_@@_tmp_tl +% \end{macrocode} +% \end{variable} +% +% \subsection{Interface functions} +% +% \begin{variable}{\l_@@_parse_bool} +% One top-level setting applies to all number cells. +% \begin{macrocode} +\keys_define:nn { siunitx / table } + { + parse .bool_set:N = \l_@@_parse_bool + } +% \end{macrocode} +% \end{variable} +% +% \begin{macro}{\siunitx_cell_begin:, \siunitx_cell_end:} +% \begin{macrocode} +\cs_new_protected:Npn \siunitx_cell_begin: + { + \bool_if:NTF \l_@@_parse_bool + { \@@_collect_begin: } + { \@@_direct_begin: } + } +\cs_new_protected:Npn \siunitx_cell_end: + { + \@@_collect_end: + } +% \end{macrocode} +% \end{macro} +% +% \subsection{Collecting tokens} +% +% \begin{variable}{\l_@@_collect_tl} +% Space for tokens. +% \begin{macrocode} +\tl_new:N \l_@@_collect_tl +% \end{macrocode} +% \end{variable} +% +% \begin{macro}{\@@_collect_begin:} +% Collecting a tabular cell means doing a token-by-token collection. +% In previous versions of \pkg{siunitx} that was done along with picking +% out the numerical part, but the code flow ends up very tricky. Here, +% therefore, we just collect up the unchanged tokens first. Some issues +% with the way that the \texttt{peek} functions are currently set up in +% \pkg{expl3} mean that at present there is a need to do stuff by hand +% here. The definition of \cs{cr} is used to allow collection of any tokens +% inserted after the main content when dealing with the last cell of a row: +% the \enquote{group} around it is needed to avoid issues with the underlying +% |\halign|. (The approach is based on that in \pkg{collcell}.) Notice that +% as each cell forms a group there is no need to reset the definition of +% \cs{cr}. +% \begin{macrocode} +\cs_new_protected:Npn \@@_collect_begin: + { + \tl_clear:N \l_@@_collect_tl + \cs_set_protected:Npn \__peek_execute_branches: + { + \if_catcode:w \exp_not:N \l_peek_token \c_group_begin_token + \exp_after:wN \@@_collect_group:n + \else: + \exp_after:wN \@@_collect_token:N + \fi: + } + \if_false: { \fi: + \cs_set_protected:Npn \cr + { + \@@_collect_loop: + \tex_cr:D + } + \if_false: } \fi: + \@@_collect_loop: + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_collect_loop:} +% \begin{macro}{\@@_collect_group:n} +% \begin{macro}{\@@_collect_token:N} +% \begin{macro}{\@@_collect_search:NnF} +% \begin{macro}{\@@_collect_search_aux:NNn} +% Collecting up the cell content needs a loop: this is done using +% a |peek| approach as it's most natural. (A slower approach is possible +% using something like the |\tl_lower_case:n| loop code.) The set of +% possible tokens is somewhat limited compared to an arbitrary cell +% (\foreign{cf.}~the approach in \pkg{collcell}): the special cases are +% pulled out for manual handling. The flexible lookup approach is more-or-less +% the same idea as in the kernel |case| functions. The |\relax| special case +% covers the case where |\\| has been expanded in an empty cell. +% \begin{macrocode} +\cs_new_protected:Npn \@@_collect_loop: + { \peek_after:Nw \__peek_ignore_spaces_execute_branches: } +\cs_new_protected:Npn \@@_collect_group:n #1 + { + \tl_put_right:Nn \l_@@_collect_tl { {#1} } + \@@_collect_loop: + } +\cs_new_protected:Npn \@@_collect_token:N #1 + { + \@@_collect_search:NnF #1 + { + \ignorespaces { \@@_collect_loop: } + \unskip { \@@_collect_loop: } + \end { \tabularnewline \end } + \relax { \relax } + \tabularnewline { \tabularnewline } + \siunitx_cell_end: { \siunitx_cell_end: } + } + { + \tl_put_right:Nn \l_@@_collect_tl {#1} + \@@_collect_loop: + } + } +\AtBeginDocument + { + \@ifpackageloaded { mdwtab } + { + \cs_set_protected:Npn \@@_collect_token:N #1 + { + \@@_collect_search:NnF #1 + { + \@maybe@unskip { \@@_collect_loop: } + \ignorespaces { \@@_collect_loop: } + \tab@setcr { \@@_collect_loop: } + \unskip { \@@_collect_loop: } + \end { \tabularnewline \end } + \relax { \relax } + \tabularnewline { \tabularnewline } + \siunitx_cell_end: { \siunitx_cell_end: } + } + { + \tl_put_right:Nn \l_@@_collect_tl {#1} + \@@_collect_loop: + } + } + } + { } + } +\cs_new_protected:Npn \@@_collect_search:NnF #1#2#3 + { + \@@_collect_search_aux:NNn #1 + #2 + #1 {#3} + \q_stop + } +\cs_new_protected:Npn \@@_collect_search_aux:NNn #1#2#3 + { + \token_if_eq_meaning:NNTF #1 #2 + { \use_i_delimit_by_q_stop:nw {#3} } + { \@@_collect_search_aux:NNn #1 } + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \subsection{Separating collected material} +% +% The input needs to be divided into numerical tokens and those which appear +% before and after them. This needs a second loop and validation. +% +% \begin{variable}{\l_@@_pre_tl, \l_@@_number_tl, \l_@@_post_tl} +% Space for tokens. +% \begin{macrocode} +\tl_new:N \l_@@_pre_tl +\tl_new:N \l_@@_number_tl +\tl_new:N \l_@@_post_tl +% \end{macrocode} +% \end{variable} +% +% \begin{macro}{\@@_collect_end:} +% At the end of the cell, expand all of the content as far as possible then +% split it up into numerical and non-numerical parts. +% \begin{macrocode} +\cs_new_protected:Npn \@@_collect_end: + { + \protected@edef \l_@@_collect_tl + { \l_@@_collect_tl } + \tl_clear:N \l_@@_pre_tl + \tl_clear:N \l_@@_number_tl + \tl_clear:N \l_@@_post_tl + \cs_set_protected:Npn \__peek_execute_branches: + { + \if_catcode:w \exp_not:N \l_peek_token \c_group_begin_token + \exp_after:wN \@@_split_group:n + \else: + \exp_after:wN \@@_split_token:N + \fi: + } + \exp_after:wN \@@_split_loop: \l_@@_collect_tl + \q_recursion_tail \q_recursion_stop + \@@_split_tidy:N \l_@@_pre_tl + \@@_split_tidy:N \l_@@_post_tl + \tl_if_empty:NTF \l_@@_number_tl + { \@@_print_text:V \l_@@_pre_tl } + { + \@@_print:VVV + \l_@@_pre_tl + \l_@@_number_tl + \l_@@_post_tl + } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_split_loop:} +% \begin{macro}{\@@_split_group:n} +% \begin{macro}{\@@_split_token:N} +% Splitting into parts uses the fact that numbers cannot contain groups +% and that we can track where we are up to based on the content of the +% token lists. +% \begin{macrocode} +\cs_new_protected:Npn \@@_split_loop: + { \peek_after:Nw \__peek_ignore_spaces_execute_branches: } +\cs_new_protected:Npn \@@_split_group:n #1 + { + \tl_if_empty:NTF \l_@@_number_tl + { \tl_put_right:Nn \l_@@_pre_tl { {#1} } } + { \tl_put_right:Nn \l_@@_post_tl { {#1} } } + \@@_split_loop: + } +\cs_new_protected:Npn \@@_split_token:N #1 + { + \quark_if_recursion_tail_stop:N #1 + \tl_if_empty:NTF \l_@@_post_tl + { + \siunitx_if_number_token:NTF #1 + { \tl_put_right:Nn \l_@@_number_tl {#1} } + { + \tl_if_empty:NTF \l_@@_number_tl + { \tl_put_right \l_@@_pre_tl {#1} } + { \tl_put_right \l_@@_post_tl {#1} } + } + } + { \tl_put_right:Nn \l_@@_post_tl {#1} } + \@@_split_loop: + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@@_split_tidy:N} +% \begin{macro}{\@@_split_tidy:Nn, \@@_split_tidy:NV} +% A quick test for the entire content being surrounded by a set of braces: +% rather than look explicitly, use the fact that a string comparison can +% detect the same thing. The auxiliary is needed to avoid having to go +% \foreign{via} a |:D| function (for the expansion behaviour). +% \begin{macrocode} +\cs_new_protected:Npn \@@_split_tidy:N #1 + { + \tl_if_empty:NF #1 + { \@@_split_tidy:NV #1 #1 } + } +\cs_new_protected:Npn \@@_split_tidy:Nn #1#2 + { + \str_if_eq_x:nnT + { \exp_not:n {#2} } + { { \exp_not:o { \use:n #2 } } } + { \tl_set:No #1 { \use:n #2 } } + } +\cs_generate_variant:Nn \@@_split_tidy:Nn { NV } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \subsection{Printing numbers in cells: spacing} +% +% 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 0pt plus 0.5fill +% \kern 0pt +% # +% \hskip 0pt plus 0.5fill +% \end{verbatim} +% which means there is \texttt{fill} stretch to worry about and the kern as +% well. +% +% \begin{macro}{\@@_skip:n} +% To prevent combination of skips, a kern is inserted after each one. +% This is best handled as a short auxiliary. +% \begin{macrocode} +\cs_new_protected:Npn \@@_skip:n #1 + { + \skip_horizontal:n {#1} + \tex_kern:D \c_zero_skip + } +% \end{macrocode} +% \end{macro} +% +% \begin{variable}{\l_@@_column_width_dim, \l_@@_fixed_width_bool} +% Settings which apply to aligned columns in general. +% \begin{macrocode} +\keys_define:nn { siunitx / table } + { + column-width .dim_set:N = + \l_@@_column_width_dim , + fixed-width .bool_set:N = + \l_@@_fixed_width_bool + } +% \end{macrocode} +% \end{variable} +% +% \begin{macro}{\@@_align_center:n, \@@_align_left:n, \@@_align_right:n} +% \begin{macro}{\@@_align_auxi:nn, \@@_align_auxii:nn} +% The beginning and end of each table cell have to adjust the position of +% the content using glue. When \pkg{colortbl} is loaded the glue is done in +% two parts: one for our positioning and one to explicitly override that from +% the package. Using a two-step auxiliary chain avoids needing to repeat any +% code and the impact of the extra expansion should be trivial. +% \begin{macrocode} +\cs_new_protected:Npn \@@_align_center:n #1 + { \@@_align_auxi:nn {#1} { 0pt plus 0.5fill } {#1} } +\cs_new_protected:Npn \@@_align_left:n #1 + { \@@_align_auxi:nn {#1} { 0pt } {#1} } +\cs_new_protected:Npn \@@_align_right:n #1 + { \@@_align_auxi:nn {#1} { 0pt plus 1fill } {#1} } +\cs_new_protected:Npn \@@_align_auxi:nn #1#2 + { + \bool_if:NTF \l_@@_fixed_width_bool + { \hbox_to_wd:nn \l_@@_column_width_dim } + { \use:n } + { + \@@_skip:n {#2} + #1 + \@@_skip:n { 0pt plus 1fill - #2 } + } + } +\AtBeginDocument + { + \@ifpackageloaded { colortbl } + { + \cs_new_eq:NN + \@@_align_auxii:nn + \@@_align_auxi:nn + \cs_set_protected:Npn \@@_align_auxi:nn #1#2 + { + \@@_skip:n{ 0pt plus -0.5fill } + \@@_align_auxii:nn {#1} {#2} + \@@_skip:n { 0pt plus -0.5fill } + } + } + { } + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \subsection{Printing just text} +% +% In cases where there is no numerical part, \pkg{siunitx} allows alignment +% of the \enquote{escaped} text independent of the underlying column type. +% +% \begin{variable}{\l_@@_align_text_tl} +% Alignment is handled using a |tl| as this allows a fast lookup at the +% point of use. +% \begin{macrocode} +\keys_define:nn { siunitx / table } + { + text-alignment .choices:nn = + { center , left , right } + { \tl_set:Nn \l_@@_align_text_tl {#1} } , + } +\tl_new:N \l_@@_align_text_tl +% \end{macrocode} +% \end{variable} +% +% \begin{macro}{\@@_print_text:n, \@@_print_text:V} +% Printing escaped text is easy: just place it in correctly in the +% column. +% \begin{macrocode} +\cs_new_protected:Npn \@@_print_text:n #1 + { + \use:c { @@_align_ \l_@@_align_text_tl :n } {#1} + } +\cs_generate_variant:Nn \@@_print_text:n { V } +% \end{macrocode} +% \end{macro} +% +% \subsection{Reserving space: the table format} +% +% \begin{variable}{\l_@@_format_tl} +% \begin{macrocode} +\keys_define:nn { siunitx / table } + { + format .tl_set:N = \l_@@_format_tl + } +% \end{macrocode} +% \end{variable} +% +% \subsection{Directly printing without collection} +% +% Collecting the number allows for various effects but is not as fast +% as simply aligning on the first token that is a decimal marker. The +% strategy here is that used by \pkg{dcolumn}. +% +% \begin{macro}{\@@_direct_begin:} +% \begin{macro}{\@@_direct_begin:w} +% \begin{macro}{\@@_direct_begin_aux:} +% After removing the |\ignorespaces| at the start of the cell, check to see +% if there is a |{| and branch as appropriate. +% \begin{macrocode} +\cs_new_protected:Npn \@@_direct_begin: + { \@@_direct_begin:w } +\cs_new_protected:Npn \@@_direct_begin:w \ignorespaces + { + \cs_set:Npn \__peek_execute_branches: + { + \if_catcode:w \exp_not:N \l_peek_token \c_group_begin_token + \exp_after:wN \@@_print_text:n + \else: + \m@th + \exp_after:wN \@@_direct_begin_aux: + \fi: + } + \peek_after:Nw \__peek_ignore_spaces_execute_branches: + } +\cs_new_protected:Npn \@@_direct_begin_aux: + { + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \subsection{Printing numbers in cells: main functions} +% +% \begin{variable} +% { +% \l_@@_align_comparator_bool , +% \l_@@_align_exponent_bool , +% \l_@@_align_uncertainty_bool , +% \l_@@_alignment_tl , +% \l_@@_parse_only_bool +% } +% Alignment is handled using a |tl| as this allows a fast lookup at the +% point of use. +% \begin{macrocode} +\keys_define:nn { siunitx / table } + { + align-comparator .bool_set:N = + \l_@@_align_comparator_bool , + align-exponent .bool_set:N = + \l_@@_align_exponent_bool , + align-uncertainty .bool_set:N = + \l_@@_align_uncertainty_bool , + alignment .choices:nn = + { center , left , right } + { \tl_set:Nn \l_@@_alignment_tl {#1} } , + parse-only .bool_set:N = + \l_@@_parse_only_bool + } +\tl_new:N \l_@@_alignment_tl +% \end{macrocode} +% \end{variable} +% +% \begin{macro}{\@@_print:nnn, \@@_print:VVV} +% \begin{macro}{\@@_print_non_aligned:nnn, \@@_print_aligned:nnn} +% \begin{macrocode} +\cs_new_protected:Npn \@@_print:nnn #1#2#3 + { + \use:c { @@_align_ \l_@@_alignment_tl :n } + { + \bool_if:NTF \l_@@_parse_only_bool + { \@@_print_non_aligned:nnn } + { \@@_print_aligned:nnn } + {#1} {#2} {#3} + } + } +\cs_generate_variant:Nn \@@_print:nnn { VVV } +\cs_new_protected:Npn \@@_print_non_aligned:nnn #1#2#3 + { + #1 + \siunitx_number_format:nN {#2} \l_@@_tmp_tl + \siunitx_print:nV { number } \l_@@_tmp_tl + #3 + } +\cs_new_protected:Npn \@@_print_aligned:nnn #1#2#3 + { + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \subsection{Standard settings for module options} +% +% Some of these follow naturally from the point of definition +% (\foreign{e.g.}~boolean variables are always |false| to begin with), +% but for clarity everything is set here. +% \begin{macrocode} +\keys_set:nn { siunitx / table } + { + align-comparator = false , + align-exponent = false , + align-uncertainty = false , + alignment = center , + column-width = 0pt , + fixed-width = false , + format = , + parse = true , + parse-only = false , + text-alignment = center + } +% \end{macrocode} +% +% +% \begin{macrocode} +%</package> +% \end{macrocode} +% +% \end{implementation} +% +% \PrintIndex
\ No newline at end of file diff --git a/Master/texmf-dist/source/latex/siunitx/siunitx-unit.dtx b/Master/texmf-dist/source/latex/siunitx/siunitx-unit.dtx new file mode 100644 index 00000000000..ea19c017b68 --- /dev/null +++ b/Master/texmf-dist/source/latex/siunitx/siunitx-unit.dtx @@ -0,0 +1,2516 @@ +% \iffalse meta-comment +% +% File: siunitx-unit.dtx Copyright (C) 2014-2018 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 +% +% https://www.latex-project.org/lppl.txt +% +% This file is part of the "siunitx bundle" (The Work in LPPL) +% and all files in that bundle must be distributed together. +% +% The released version of this bundle is available from CTAN. +% +% ----------------------------------------------------------------------- +% +% The development version of the bundle can be found at +% +% https://github.com/josephwright/siunitx +% +% for those people who are interested. +% +% ----------------------------------------------------------------------- +% +%<*driver> +\documentclass{l3doc} +% The next line is needed so that \GetFileInfo will be able to pick up +% version data +\usepackage{siunitx} +\begin{document} + \DocInput{\jobname.dtx} +\end{document} +%</driver> +% \fi +% +% \GetFileInfo{siunitx.sty} +% +% \title{^^A +% \pkg{siunitx-unit} -- Parsing and formatting units^^A +% \thanks{This file describes \fileversion, +% last revised \filedate.}^^A +% } +% +% \author{^^A +% Joseph Wright^^A +% \thanks{^^A +% E-mail: +% \href{mailto:joseph.wright@morningstar2.co.uk} +% {joseph.wright@morningstar2.co.uk}^^A +% }^^A +% } +% +% \date{Released \filedate} +% +% \maketitle +% +% \begin{documentation} +% +% This submodule is dedicated to formatting physical units. The main function, +% \cs{siunitx_unit_format:nN}, takes user input specify physical units and +% converts it into a formatted token list suitable for typesetting in math +% mode. While the formatter will deal correctly with \enquote{literal} user +% input, the key strength of the module is providing a method to describe +% physical units in a \enquote{symbolic} manner. The output format of these +% symbolic units can then be controlled by a number of key--value options +% made available by the module. +% +% A small number of \LaTeXe{} math mode commands are assumed to be available +% as part of the formatted output. The \cs{mathchoice} command +% (normally the \TeX{} primitive) is needed when using +% |per-mode = symbol-or-fraction|. The command \cs{mathrm} is used for +% wrapping the text (letter) part of units. The commands \cs{frac}, +% \cs{mbox}, \verb*|\ | and \cs{,} are used by the standard module settings, +% and \cs{ensuremath}, \cs{hbar}, \cs{mathit} and \cs{mathrm} in some standard +% unit definitions (for atomic and natural units). For the display of colored +% (highlighted) and cancelled units, the commands \cs{textcolor} and +% \cs{cancel} are assumed to be available. +% +% \section{Formatting units} +% +% \begin{function}{\siunitx_unit_format:nN} +% \begin{syntax} +% \cs{siunitx_unit_format:nN} \Arg{units} \meta{tl~var} +% \end{syntax} +% This function converts the input \meta{units} into a processed +% \meta{tl~var} which can then be inserted in math mode to typeset the +% material. Where the \meta{units} are given in symbolic form, described +% elsewhere, this formatting process takes place in two stages: the +% \meta{units} are parsed into a structured form before the generation +% of the appropriate output form based on the active settings. When the +% \meta{units} are given as literals, processing is minimal: the +% characters |.| and |~| are converted to unit products (boundaries). +% In both cases, the result is a series of tokens intended to be typeset +% in math mode with appropriate choice of font for typesetting of the +% textual parts. +% +% For example, +% \begin{verbatim} +% \siunitx_unit_format:nN { \kilo \metre \per \second } \l_tmpa_tl +% \end{verbatim} +% will, with standard settings, result in \cs{l_tmpa_tl} being set to +% \begin{verbatim} +% \mathrm{km}\,\mathrm{s}^{-1} +% \end{verbatim} +% \end{function} +% +% \begin{function}{\siunitx_unit_format:nNN} +% \begin{syntax} +% \cs{siunitx_unit_format:nNN} \Arg{units} \meta{tl~var} \meta{fp~var} +% \end{syntax} +% This function formats the \meta{units} in the same way as described for +% \cs{siunitx_unit_format:nN}. When the input is given in symbolic form, +% any decimal unit prefixes will be extracted and the overall power of +% ten that these represent will be stored in the \meta{fp~var}. +% +% For example, +% \begin{verbatim} +% \siunitx_unit_format:nNN { \kilo \metre \per \second } +% \l_tmpa_tl \l_tmpa_fp +% \end{verbatim} +% will, with standard settings, result in \cs{l_tmpa_tl} being set to +% \begin{verbatim} +% \mathrm{m}\,\mathrm{s}^{-1} +% \end{verbatim} +% with \cs{l_tmpa_fp} taking value~$3$. Note that the latter is a floating +% point variable: it is possible for non-integer values to be obtained here. +% \end{function} +% +% \section{Defining symbolic units} +% +% \begin{function}{\siunitx_declare_prefix:Nnn} +% \begin{syntax} +% \cs{siunitx_declare_prefix:Nnn} \meta{prefix} \Arg{symbol} \Arg{power} +% \end{syntax} +% Defines a symbolic \meta{prefix} (which should be a control sequence +% such as |\kilo|) to be converted by the parser to the \meta{symbol}. +% The latter should consist of literal content (\emph{e.g.}~|k|). +% In literal mode the \meta{symbol} will be typeset directly. The prefix +% should represent an integer \meta{power} of $10$, and this information +% may be used to convert from one or more \meta{prefix} symbols to an +% overall power applying to a unit. See also +% \cs{siunitx_declare_prefix:Nn}. +% \end{function} +% +% \begin{function}{\siunitx_declare_prefix:Nn} +% \begin{syntax} +% \cs{siunitx_declare_prefix:Nn} \meta{prefix} \Arg{symbol} +% \end{syntax} +% Defines a symbolic \meta{prefix} (which should be a control sequence +% such as |\kilo|) to be converted by the parser to the \meta{symbol}. +% The latter should consist of literal content (\emph{e.g.}~|k|). +% In literal mode the \meta{symbol} will be typeset directly. In contrast +% to \cs{siunitx_declare_prefix:Nnn}, there is no assumption about the +% mathematical nature of the \meta{prefix}, \emph{i.e.}~the prefix may +% represent a power of any base. As a result, no conversion of the +% \meta{prefix} to a numerical power will be possible. +% \end{function} +% +% \begin{function}{\siunitx_declare_power:NNn} +% \begin{syntax} +% \cs{siunitx_declare_power:NnN} \meta{pre-power} \meta{post-power} \Arg{value} +% \end{syntax} +% Defines \emph{two} symbolic \meta{powers} (which should be control +% sequences such as |\squared|) to be converted by the parser to the +% \meta{value}. The latter should be an integer or floating point number in +% the format defined for \pkg{l3fp}. Powers may precede a unit or be give +% after it: both forms are declared at once, as indicated by the argument +% naming. In literal mode, the \meta{value} will be applied as +% a superscript to either the next token in the input (for the +% \meta{pre-power}) or appended to the previously-typeset material +% (for the \meta{post-power}). +% \end{function} +% +% \begin{function}{\siunitx_declare_qualifier:Nn} +% \begin{syntax} +% \cs{siunitx_declare_qualifier:Nn} \meta{qualifier} \Arg{meaning} +% \end{syntax} +% Defines a symbolic \meta{qualifier} (which should be a control sequence +% such as |\catalyst|) to be converted by the parser to the \meta{meaning}. +% The latter should consist of literal content (\emph{e.g.}~|cat|). In +% literal mode the \meta{meaning} will be typeset following a space after +% the unit to which it applies. +% \end{function} +% +% \begin{function}{\siunitx_declare_unit:Nn, \siunitx_declare_unit:Nx} +% \begin{syntax} +% \cs{siunitx_declare_unit:Nn} \meta{unit} \Arg{meaning} +% \end{syntax} +% Defines a symbolic \meta{unit} (which should be a control sequence +% such as |\kilogram|) to be converted by the parser to the \meta{meaning}. +% The latter may consist of literal content (\emph{e.g.}~|kg|), other +% symbolic unit commands (\emph{e.g.}~|\kilo\gram|) or a mixture of the two. +% In literal mode the \meta{meaning} will be typeset directly. +% \end{function} +% +% \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{Pre-defined symbolic unit components} +% +% The unit parser is defined to recognise a number of pre-defined units, +% prefixes and powers, and also interpret a small selection of +% \enquote{generic} symbolic parts. +% +% Broadly, the pre-defined units are those defined by the \textsc{bipm} in the +% documentation for the \emph{International System of Units} (SI)~\cite{BIPM}. +% As far as possible, the names given to the command names for units are those +% used by the \textsc{bipm}, omitting spaces and using only \textsc{ascii} +% characters. The standard symbols are also taken from the same documentation. +% In the following documentation, the order of the description of units +% broadly follows the SI~Brochure. +% +% \begin{function} +% { +% \kilogram , +% \metre , +% \meter , +% \mole , +% \kelvin , +% \candela , +% \second , +% \ampere +% } +% The base units as defined in Section~2.1 of the SI Brochure~\cite{SI:2.1}. +% Notice that \cs{meter} is defined as an alias for \cs{metre} as the former +% spelling is common in the US (although the latter is the official spelling). +% \end{function} +% +% \begin{function}{\gram} +% The base unit \cs{kilogram} is defined using an SI prefix: as such the +% (derived) unit \cs{gram} is required by the module to correctly produce +% output for the \cs{kilogram}. +% \end{function} +% +% \begin{function} +% { +% \yocto , +% \zepto , +% \atto , +% \femto , +% \pico , +% \nano , +% \micro , +% \milli , +% \centi , +% \deci , +% \deca , +% \deka , +% \hecto , +% \kilo , +% \mega , +% \giga , +% \tera , +% \peta , +% \exa , +% \zetta , +% \yotta +% } +% Prefixes, all of which are integer powers of $10$: the powers are stored +% internally by the module and can be used for conversion from prefixes to +% their numerical equivalent. These prefixes are documented in Section~3.1 +% of the SI~Brochure~\cite{SI:3.1}. +% +% Note that the \cs{kilo} prefix is required to +% define the base \cs{kilogram} unit. Also note the two spellings available +% for \cs{deca}/\cs{deka}. +% \end{function} +% +% \begin{function} +% { +% \becquerel , +% \degreeCelsius , +% \coulomb , +% \farad , +% \gray , +% \hertz , +% \henry , +% \joule , +% \katal , +% \lumen , +% \lux , +% \newton , +% \ohm , +% \pascal , +% \radian , +% \siemens , +% \sievert , +% \steradian , +% \tesla , +% \volt , +% \watt , +% \weber +% } +% The defined SI~units with defined names and symbols, as given in +% Section~2.2.2 of the SI~Brochure~\cite{SI:2.2.2}. Notice that the names +% of the units are lower case with the exception of \cs{degreeCelsius}, and +% that this unit name includes \enquote{degree}. +% \end{function} +% +% \begin{function} +% { +% \day , +% \hectare , +% \hour , +% \litre , +% \liter , +% \minute , +% \tonne +% } +% Units accepted for use with the SI: here \cs{minute} is a unit of time +% not of plane angle. These units are taken from Table~4.1 of the +% SI~Brochure~\cite{SI:T6}. +% +% For the unit \cs{litre}, both |l| and |L| are listed +% as acceptable symbols: the latter is the standard setting of the module. +% The alternative spelling \cs{liter} is also given for this unit for US +% users (as with \cs{metre}, the official spelling is \enquote{re}). +% \end{function} +% +% \begin{function} +% { +% \arcminute , +% \arcsecond , +% \degree +% } +% Units for plane angles accepted for use with the SI: to avoid a clash +% with units for time, here \cs{arcminute} and \cs{arcsecond} are used in +% place of \cs{minute} and \cs{second}. These units are taken from Table~4.1 +% of the SI~Brochure~\cite{SI:T6}. +% \end{function} +% +% \begin{function} +% { +% \astronomicalunit , +% \atomicmassunit , +% \auaction , +% \aucharge , +% \auenergy , +% \aulength , +% \aumass , +% \autime , +% \bohr , +% \dalton , +% \electronvolt , +% \hartree , +% \nuaction , +% \numass , +% \nuspeed , +% \nutime +% } +% Non-SI where values must be determined experimentally. These units are taken from +% Table~7 of the SI~Brochure~\cite{SI:T7}. Where no better name is given for +% the unit in the SI~Brochure, the prefixes |nu| (natural unit) and |au| (atomic +% unit) are used. +% +% Note that the value of the natural unit of speed (the speed of light) is used +% to define the second and is thus not determined by experiment: it is however +% included in this set of units. +% \end{function} +% +% \begin{function} +% { +% \angstrom , +% \bar , +% \barn , +% \bel , +% \decibel , +% \knot , +% \millimetremercury , +% \nauticalmile , +% \neper +% } +% Non-SI units accepted for use with the SI. These units are taken from +% Table~8 of the SI~Brochure~\cite{SI:T8}. +% \end{function} +% +% \begin{function} +% { +% \dyne , +% \erg , +% \gal , +% \gauss , +% \maxwell , +% \oersted , +% \phot , +% \poise , +% \stilb , +% \stokes +% } +% Non-SI units associated with the CGS and the CGS-Gaussian system of units. +% These units are taken from Table~9 of the SI~Brochure~\cite{SI:T9}. +% \end{function} +% +% \begin{function}{\percent} +% The mathematical concept of percent, usable with the SI as detailed in +% Section~5.3.7 of the SI~Brochure~\cite{SI:5.3.7}. +% \end{function} +% +% \begin{function}{\square, \cubic} +% \begin{syntax} +% \cs{square} \meta{prefix} \meta{unit} +% \cs{cubic} \meta{prefix} \meta{unit} +% \end{syntax} +% Pre-defined unit powers which apply to the next \meta{prefix}/\meta{unit} +% combination. +% \end{function} +% +% \begin{function}{\squared, \cubed} +% \begin{syntax} +% \meta{prefix} \meta{unit} \cs{squared} +% \meta{prefix} \meta{unit} \cs{cubed} +% \end{syntax} +% Pre-defined unit powers which apply to the preceding +% \meta{prefix}/\meta{unit} combination. +% \end{function} +% +% \begin{function}{\per} +% \begin{syntax} +% \cs{per} \meta{prefix} \meta{unit} \meta{power} +% \end{syntax} +% Indicates that the next \meta{prefix}/\meta{unit}/\meta{power} combination +% is reciprocal, \emph{i.e.}~raises it to the power $-1$. This symbolic +% representation may be applied in addition to a \cs{power}, and will work +% correctly if the \cs{power} itself is negative. In literal mode \cs{per} +% will print a slash (\enquote{$/$}). +% \end{function} +% +% \begin{function}{\cancel} +% \begin{syntax} +% \cs{cancel} \meta{prefix} \meta{unit} \meta{power} +% \end{syntax} +% Indicates that the next \meta{prefix}/\meta{unit}/\meta{power} combination +% should be \enquote{cancelled out}. In the parsed output, the entire unit +% combination will be given as the argument to a function \cs{cancel}, which +% is assumed to be available at a higher level. In literal mode, the same +% higher-level \cs{cancel} will be applied to the next token. It is the +% responsibility of the calling code to provide an appropriate definition +% for \cs{cancel} outside of the scope of the unit parser. +% \end{function} +% +% \begin{function}{\highlight} +% \begin{syntax} +% \cs{highlight} \Arg{color} \meta{prefix} \meta{unit} \meta{power} +% \end{syntax} +% Indicates that the next \meta{prefix}/\meta{unit}/\meta{power} combination +% should be highlighted in the specified \meta{color}. In the parsed output, +% the entire unit combination will be given as the argument to a function +% \cs{textcolor}, which is assumed to be available at a higher level. In +% literal mode, the same higher-level \cs{textcolor} will be applied to the +% next token. It is the responsibility of the calling code to provide an +% appropriate definition for \cs{textcolor} outside of the scope of the unit +% parser. +% \end{function} +% +% \begin{function}{\of} +% \begin{syntax} +% \meta{prefix} \meta{unit} \meta{power} \cs{of} \Arg{qualifier} +% \end{syntax} +% Indicates that the \meta{qualifier} applies to the current +% \meta{prefix}/\meta{unit}/\meta{power} combination. In parsed mode, the +% display of the result will depend upon module options. In literal mode, +% the \meta{qualifier} will be printed in parentheses following the preceding +% \meta{unit} and a full-width space. +% \end{function} +% +% \begin{function}{\raiseto, \tothe} +% \begin{syntax} +% \cs{raiseto} \Arg{power} \meta{prefix} \meta{unit} +% \meta{prefix} \meta{unit} \cs{tothe} \Arg{power} +% \end{syntax} +% Indicates that the \meta{power} applies to the current +% \meta{prefix}/\meta{unit} combination. As shown, \cs{raiseto} applies to +% the next \meta{unit} whereas \cs{tothe} applies to the preceding unit. In +% literal mode the \cs{power} will be printed as a superscript attached to +% the next token (\cs{raiseto}) or preceding token (\cs{tothe}) as +% appropriate. +% \end{function} +% +% \subsection{Key--value options} +% +% The options defined by this submodule are available within the \pkg{l3keys} +% |siunitx| tree. +% +% \begin{function}{bracket-denominator} +% \begin{syntax} +% |bracket-denominator| = |true|\verb"|"|false| +% \end{syntax} +% Switch to determine whether brackets are added to the denominator part of +% a unit when printed using inline fractional form (with |per-mode| as +% |repeated-symbol|, |symbol| or |symbol-or-fraction|). The standard setting +% is |true|. +% \end{function} +% +% \begin{function}{fraction-command} +% \begin{syntax} +% |fraction-command| = \meta{command} +% \end{syntax} +% Command used to create fractional output when |per-mode| is set to +% |fraction|. The standard setting is |\frac|. +% \end{function} +% +% \begin{function}{parse-units} +% \begin{syntax} +% |parse-units| = |true|\verb"|"|false| +% \end{syntax} +% Determines whether parsing of unit symbols is attempted or literal +% mode is used directly. The standard setting is |true|. +% \end{function} +% +% \begin{function}{per-mode} +% \begin{syntax} +% |per-mode| = \meta{choice} +% \end{syntax} +% Selects how the negative powers (\cs{per}) are formatted: a choice from +% the options |fraction|, |power|, |power-positive-first|, |repeated-symbol|, +% |symbol| and |symbol-or-fraction|. The option |fraction| generates +% fractional output when appropriate using the command specified by +% the |fraction-command| option. The setting |power| uses reciprocal powers +% leaving the units in the order of input, while |power-positive-first| uses +% the same display format but sorts units such that the positive powers +% come before negative ones. The |symbol| setting uses a symbol (specified +% by |per-symbol|) between positive and negative powers, while +% |repeated-symbol| uses the same symbol but places it before \emph{every} +% unit with a negative power (this is mathematically \enquote{wrong} but +% often seen in real work). Finally, |symbol-or-fraction| acts like +% |symbol| for inline output and like |fraction| when the output is used +% in a display math environment. The standard setting is |power|. +% \end{function} +% +% \begin{function}{per-symbol} +% \begin{syntax} +% |per-symbol| = \meta{symbol} +% \end{syntax} +% Specifies the symbol to be used to denote negative powers when the option +% |per-mode| is set to |repeated-symbol|, |symbol| or |symbol-or-fraction|. +% The standard setting is |/|. +% \end{function} +% +% \begin{function}{qualifier-mode} +% \begin{syntax} +% |qualifier-mode| = \meta{choice} +% \end{syntax} +% Selects how qualifiers are formatted: a choice from the options |brackets|, +% |combine|, |phrase| and |subscript|. The option |bracket| wraps +% the qualifier in parenthesis, |combine| joins the qualifier with the unit +% directly, |phrase| inserts the content stored by the option +% |qualifier-phrase| between the unit and qualifier, and |subscript| formats +% the qualifier as a subscript. The standard setting is |subscript|. +% \end{function} +% +% \begin{function}{qualifier-phrase} +% \begin{syntax} +% |qualifier-phrase| = \meta{choice} +% \end{syntax} +% Defines the text to be inserted between a unit and qualifier when +% |qualifier-mode| is set to |phrase|. This material is inserted without +% any font control and so if text mode is required it should be +% included in the setting, for example \verb*|\ \mbox{of}\ |. The +% standard setting is a full width space (\verb*|\ |). +% \end{function} +% +% \begin{function}{sticky-per} +% \begin{syntax} +% |sticky-per| = |true|\verb"|"|false| +% \end{syntax} +% Used to determine whether \cs{per} should be applied one a unit-by-unit +% basis (when |false|) or should apply to all following units +% (when |true|). The latter mode is somewhat akin conceptually to the +% \TeX{} \cs{over} primitive. The standard setting is |false|. +% \end{function} +% +% \begin{function}{unit-close-bracket} +% \begin{syntax} +% |unit-close-bracket| = \meta{symbol} +% \end{syntax} +% Bracket symbol used to close a matched pair around units when once is +% required to maintain mathematical logic. The standard setting is ^^A ( +% |)|. +% \end{function} +% +% \begin{function}{unit-open-bracket} +% \begin{syntax} +% |unit-open-bracket| = \meta{symbol} +% \end{syntax} +% Bracket symbol used to open a matched pair around units when once is +% required to maintain mathematical logic. The standard setting is |(|. ^^A ) +% \end{function} +% +% \begin{function}{unit-product} +% \begin{syntax} +% |unit-product| = \meta{separator} +% \end{syntax} +% Inserted between unit combinations in parsed mode, and used to replace +% |.| and |~| in literal mode. The standard setting is |\,|. +% \end{function} +% +% \end{documentation} +% +% \begin{implementation} +% +% \section{\pkg{siunitx-unit} implementation} +% +% Start the \pkg{DocStrip} guards. +% \begin{macrocode} +%<*package> +% \end{macrocode} +% +% Identify the internal prefix (\LaTeX3 \pkg{DocStrip} convention): only +% internal material in this \emph{submodule} should be used directly. +% \begin{macrocode} +%<@@=siunitx_unit> +% \end{macrocode} +% +% \subsection{Initial set up} +% +% The mechanisms defined here need a few variables to exist and to be +% correctly set: these don't belong to one subsection and so are created +% in a small general block. +% +% Variants not provided by \pkg{expl3}. +% \begin{macrocode} +\cs_generate_variant:Nn \tl_replace_all:Nnn { NnV } +% \end{macrocode} +% +% \begin{variable}{\l_@@_tmp_fp} +% \begin{variable}{\l_@@_tmp_int} +% \begin{variable}{\l_@@_tmp_tl} +% Scratch space. +% \begin{macrocode} +\fp_new:N \l_@@_tmp_fp +\int_new:N \l_@@_tmp_int +\tl_new:N \l_@@_tmp_tl +% \end{macrocode} +% \end{variable} +% \end{variable} +% \end{variable} +% +% \begin{variable}{\c_@@_math_subscript_tl} +% Useful tokens with awkward category codes. +% \begin{macrocode} +\tl_const:Nx \c_@@_math_subscript_tl + { \char_generate:nn { `\_ } { 8 } } +% \end{macrocode} +% \end{variable} +% +% \begin{variable}{\l_@@_parsing_bool} +% A boolean is used to indicate when the symbolic unit functions should +% produce symbolic or literal output. This is used when the symbolic names +% are used along with literal input, and ensures that there is a sensible +% fall-back for these cases. +% \begin{macrocode} +\bool_new:N \l_@@_parsing_bool +% \end{macrocode} +% \end{variable} +% +% \begin{variable}{\l_@@_test_bool} +% A switch used to indicate that the code is testing the input to find +% if there is any typeset output from individual unit macros. This is needed +% to allow the \enquote{base} macros to be found, and also to pick up the +% difference between symbolic and literal unit input. +% \begin{macrocode} +\bool_new:N \l_@@_test_bool +% \end{macrocode} +% \end{variable} +% +% \begin{macro}{\@@_if_symbolic:nTF} +% The test for symbolic units is needed in two places. First, there is the +% case of \enquote{pre-parsing} input to check if it can be parsed. Second, +% when parsing there is a need to check if the current unit is built up +% from others (symbolic) or is defined in terms of some literals. To do this, +% the approach used is to set all of the symbolic unit commands expandable +% and to do nothing, with the few special cases handled manually. If +% an \texttt{f}-type definition then yields nothing at all then the +% assumption is that the input is symbolic. (We use \texttt{f}-type +% expansion since it will turn the symbolic unit names into nothing at +% all but doesn't require them to be expandable.) +% \begin{macrocode} +\prg_new_protected_conditional:Npnn \@@_if_symbolic:n #1 { TF } + { + \group_begin: + \bool_set_true:N \l_@@_test_bool + \tl_set:Nf \l_@@_tmp_tl {#1} + \exp_args:NNV \group_end: + \tl_if_blank:nTF \l_@@_tmp_tl + { \prg_return_true: } + { \prg_return_false: } + } +% \end{macrocode} +% \end{macro} +% +% \subsection{Defining symbolic unit} +% +% Unit macros and related support are created here. These exist only within +% the scope of the unit processor code, thus not polluting document-level +% namespace and allowing overlap with other areas in the case of useful short +% names (for example \cs{pm}). Setting up the mechanisms to allow this requires +% a few additional steps on top of simply saving the data given by the user +% in creating the unit. +% +% \begin{variable}{\l_siunitx_unit_symbolic_seq} +% A list of all of the symbolic units, \emph{etc.}, set up. This is needed +% to allow the symbolic names to be defined within the scope of the unit +% parser but not elsewhere using simple mappings. +% \begin{macrocode} +\seq_new:N \l_siunitx_unit_symbolic_seq +% \end{macrocode} +% \end{variable} +% +% \begin{macro}{\@@_set_symbolic:Nnn} +% \begin{macro}{\@@_set_symbolic:Npnn} +% \begin{macro}{\@@_set_symbolic:NNpnn} +% The majority of the work for saving each symbolic definition is the same +% irrespective of the item being defined (unit, prefix, power, qualifier). +% This is therefore all carried out in a single internal function which +% does the common tasks. The three arguments here are the symbolic macro +% name, the literal output and the code to insert when doing full unit +% parsing. To allow for the \enquote{special cases} (where arguments are +% required) the entire mechanism is set up in a two-part fashion allowing +% for flexibility at the slight cost of additional functions. +% +% Importantly, notice that the unit macros are declared as expandable. This +% is required so that literals can be correctly converted into a token list +% of material which does not depend on local redefinitions for the unit +% macros. That is required so that the unit formatting system can be grouped. +% \begin{macrocode} +\cs_new_protected:Npn \@@_set_symbolic:Nnn #1 + { \@@_set_symbolic:NNnnn \cs_set:cpn #1 { } } +\cs_new_protected:Npn \@@_set_symbolic:Npnn #1#2# + { \@@_set_symbolic:NNnnn \cs_set:cpn #1 {#2} } +\cs_new_protected:Npn \@@_set_symbolic:NNnnn #1#2#3#4#5 + { + \seq_put_right:Nn \l_siunitx_unit_symbolic_seq {#2} + #1 { units ~ > ~ \token_to_str:N #2 } #3 + { + \bool_if:NF \l_@@_test_bool + { + \bool_if:NTF \l_@@_parsing_bool + {#5} + {#4} + } + } + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\siunitx_declare_power:NNn} +% Powers can come either before or after the unit. As they always come +% (logically) in matching, we handle this by declaring two commands, +% and setting each up separately. +% \begin{macrocode} +\cs_new_protected:Npn \siunitx_declare_power:NNn #1#2#3 + { + \@@_set_symbolic:Nnn #1 + { \@@_literal_power:nN {#1} } + { \@@_parse_power:nnN {#1} {#3} \c_true_bool } + \@@_set_symbolic:Nnn #2 + { ^ {#3} } + { \@@_parse_power:nnN {#2} {#3} \c_false_bool } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\siunitx_declare_prefix:Nn} +% \begin{macro}{\siunitx_declare_prefix:Nnn} +% \begin{variable} +% {\l_@@_prefixes_forward_prop, \l_@@_prefixes_reverse_prop} +% For prefixes there are a couple of options. In all cases, the basic +% requirement is to set up to parse the prefix using the appropriate +% internal function. For prefixes which are powers of $10$, there is also +% the need to be able to do conversion to/from the numerical equivalent. +% That is handled using two properly lists which can be used to supply +% the conversion data later. +% \begin{macrocode} +\cs_new_protected:Npn \siunitx_declare_prefix:Nn #1#2 + { + \@@_set_symbolic:Nnn #1 + {#2} + { \@@_parse_prefix:Nn #1 {#2} } + } +\cs_new_protected:Npn \siunitx_declare_prefix:Nnn #1#2#3 + { + \siunitx_declare_prefix:Nn #1 {#2} + \prop_put:Nnn \l_@@_prefixes_forward_prop {#2} {#3} + \prop_put:Nnn \l_@@_prefixes_reverse_prop {#3} {#2} + } +\prop_new:N \l_@@_prefixes_forward_prop +\prop_new:N \l_@@_prefixes_reverse_prop +% \end{macrocode} +% \end{variable} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\siunitx_declare_qualifier:Nn} +% Qualifiers are relatively easy to handle: nothing to do other than save +% the input appropriately. +% \begin{macrocode} +\cs_new_protected:Npn \siunitx_declare_qualifier:Nn #1#2 + { + \@@_set_symbolic:Nnn #1 + { \ ( #2 ) } + { \@@_parse_qualifier:nn {#1} {#2} } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\siunitx_declare_unit:Nn, \siunitx_declare_unit:Nx} +% For the unit parsing, allowing for variations in definition order requires +% that a test is made for the output of each unit at point of use. +% \begin{macrocode} +\cs_new_protected:Npn \siunitx_declare_unit:Nn #1#2 + { + \@@_set_symbolic:Nnn #1 + {#2} + { + \@@_if_symbolic:nTF {#2} + {#2} + { \@@_parse_unit:Nn #1 {#2} } + } + } +\cs_generate_variant:Nn \siunitx_declare_unit:Nn { Nx } +% \end{macrocode} +% \end{macro} +% +% \subsection{Non-standard symbolic units} +% +% A few of the symbolic units require non-standard definitions: these are +% created here. They all use parts of the more general code but have particular +% requirements which can only be addressed by hand. Some of these could in +% principle be used in place of the dedicated definitions above, but at point +% of use that would then require additional expansions for each unit parsed: +% as the macro names would still be needed, this does not offer any real +% benefits. +% +% \begin{macro}{\per} +% The \cs{per} symbolic unit is a bit special: it has a mechanism entirely +% different from everything else, so has to be set up by hand. In literal +% mode it is represented by a very simple symbol! +% \begin{macrocode} +\@@_set_symbolic:Nnn \per + { / } + { \@@_parse_per: } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\cancel} +% \begin{macro}{\highlight} +% The two special cases, \cs{cancel} and \cs{highlight}, are easy to deal +% with when parsing. When not parsing, a precaution is taken to ensure that +% the user level equivalents always get a braced argument. +% \begin{macrocode} +\@@_set_symbolic:Npnn \cancel + { \@@_literal_special:nN { \cancel } } + { \@@_parse_special:n { \cancel } } +\@@_set_symbolic:Npnn \highlight #1 + { \@@_literal_special:nN { \textcolor {#1} } } + { \@@_parse_special:n { \textcolor {#1} } } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\of} +% The generic qualifier is simply the same as the dedicated ones except for +% needing to grab an argument. +% \begin{macrocode} +\@@_set_symbolic:Npnn \of #1 + { \ ( #1 ) } + { \@@_parse_qualifier:nn { \of {#1} } {#1} } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\raiseto, \tothe} +% Generic versions of the pre-defined power macros. These require an +% argument and so cannot be handled using the general approach. Other than +% that, the code here is very similar to that in +% \cs{siunitx_unit_power_set:NnN}. +% \begin{macrocode} +\@@_set_symbolic:Npnn \raiseto #1 + { \@@_literal_power:nN {#1} } + { \@@_parse_power:nnN { \raiseto {#1} } {#1} \c_true_bool } +\@@_set_symbolic:Npnn \tothe #1 + { ^ {#1} } + { \@@_parse_power:nnN { \tothe {#1} } {#1} \c_false_bool } +% \end{macrocode} +% \end{macro} +% +% \subsection{Main formatting routine} +% +% Unit input can take two forms, \enquote{literal} units (material to be +% typeset directly) or \enquote{symbolic} units (macro-based). Before any +% parsing or typesetting is carried out, a small amount of pre-parsing has to +% be carried out to decide which of these cases applies. +% +% \begin{variable}{\l_@@_product_tl} +% Options which apply to the main formatting routine, and so are not tied +% to either symbolic or literal input. +% \begin{macrocode} +\keys_define:nn { siunitx } + { + unit-product .tl_set:N = \l_@@_product_tl + } +% \end{macrocode} +% \end{variable} +% +% \begin{variable}{\l_@@_formatted_tl} +% A token list for the final formatted result: may or may not be generated +% by the parser, depending on the nature of the input. +% \begin{macrocode} +\tl_new:N \l_@@_formatted_tl +% \end{macrocode} +% \end{variable} +% +% \begin{macro}{\siunitx_unit_format:nN} +% \begin{macro}{\siunitx_unit_format:nNN} +% \begin{macro}{\@@_format:nNN} +% \begin{macro}{\@@_format_aux:} +% Formatting parsed units can take place either with the prefixes printed or +% separated out into a power of ten. This variation is handled using two +% separate functions: as this submodule does not really deal with numbers, +% formatting the numeral part here would be tricky and it is better therefore +% to have a mechanism to return a simple numerical power. At the same time, +% most uses will no want this more complex return format and so a version of +% the code which does not do this is also provided. +% +% The main unit formatting routine groups all of the parsing/formatting, so +% that the only value altered will be the return token list. As definitions +% for the various unit macros are not globally created, the first step is to +% map over the list of names and active the unit definitions: these do +% different things depending on the switches set. There is then a decision to +% be made: is the unit input one that can be parsed (\enquote{symbolic}), or +% is is one containing one or more literals. In the latter case, there is a +% still the need to convert the input into an expanded token list as some +% parts of the input could still be using unit macros. +% +% Notice that for \cs{siunitx_unit_format:nN} a second return value from the +% auxiliary has to be allowed for, but is simply discarded. +% \begin{macrocode} +\cs_new_protected:Npn \siunitx_unit_format:nN #1#2 + { + \bool_set_false:N \l_@@_prefix_power_bool + \@@_format:nNN {#1} #2 \l_@@_tmp_fp + } +\cs_new_protected:Npn \siunitx_unit_format:nNN #1#2#3 + { + \bool_set_true:N \l_@@_prefix_power_bool + \@@_format:nNN {#1} #2 #3 + } +\cs_new_protected:Npn \@@_format:nNN #1#2#3 + { + \group_begin: + \seq_map_inline:Nn \l_siunitx_unit_symbolic_seq + { \cs_set_eq:Nc ##1 { units ~ > ~ \token_to_str:N ##1 } } + \tl_clear:N \l_@@_formatted_tl + \fp_zero:N \l_@@_prefix_fp + \bool_if:NTF \l_@@_parse_bool + { + \@@_if_symbolic:nTF {#1} + { + \@@_parse:n {#1} + \prop_if_empty:NF \l_@@_parsed_prop + { \@@_format_parsed: } + } + { \@@_format_literal:n {#1} } + } + { \@@_format_literal:n {#1} } + \cs_set_protected:Npx \@@_format_aux: + { + \tl_set:Nn \exp_not:N #2 + { \exp_not:V \l_@@_formatted_tl } + \fp_set:Nn \exp_not:N #3 + { \fp_use:N \l_@@_prefix_fp } + } + \exp_after:wN \group_end: + \@@_format_aux: + } +\cs_new_protected:Npn \@@_format_aux: { } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \subsection{Formatting literal units} +% +% While in literal mode no parsing occurs, there is a need to provide a few +% auxiliary functions to handle one or two special cases. +% +% \begin{macro}{\@@_literal_power:nN} +% For printing literal units which are given before the unit they apply to, +% there is a slight rearrangement. +% \begin{macrocode} +\cs_new_protected:Npn \@@_literal_power:nN #1#2 { #2 ^ {#1} } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_literal_special:nN} +% When dealing with the special cases, there is an argument to absorb. This +% should be braced to be passed up to the user level, which is dealt with +% here. +% \begin{macrocode} +\cs_new_protected:Npn \@@_literal_special:nN #1#2 { #1 {#2} } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_format_literal:n} +% \begin{macro}{\@@_format_literal_auxi:w} +% \begin{macro}{\@@_format_literal_auxii:w} +% \begin{macro}{\@@_format_literal_auxiii:w} +% \begin{macro}{\@@_format_literal_auxiv:w} +% \begin{macro}{\@@_format_literal_auxv:w} +% \begin{variable}{\l_@@_separator_tl} +% To format literal units, there are two tasks to do. The input is +% \texttt{x}-type expanded to force any symbolic units to be converted into +% their literal representation: this requires setting the appropriate +% switch. In the resulting token list, all |.| and |~| tokens are then +% replaced by the current unit product token list. To enable this to happen +% correctly with a normal (active) |~|, a small amount of +% \enquote{protection} is needed first. +% +% As with other code dealing with user input, \cs{protected@edef} is used +% here rather than \cs{tl_set:Nx} as \LaTeXe{} robust commands may be +% present. +% \begin{macrocode} +\group_begin: + \char_set_catcode_active:n { `\~ } + \cs_new_protected:Npx \@@_format_literal:n #1 + { + \group_begin: + \exp_not:n { \bool_set_false:N \l_@@_parsing_bool } + \tl_set:Nn \exp_not:N \l_@@_tmp_tl {#1} + \tl_replace_all:Nnn \exp_not:N \l_@@_tmp_tl + { \exp_not:N ~ } { . } + \tl_replace_all:Nnn \exp_not:N \l_@@_tmp_tl + { \token_to_str:N ^ } { ^ } + \tl_replace_all:Nnn \exp_not:N \l_@@_tmp_tl + { \token_to_str:N _ } { \c_@@_math_subscript_tl } + \exp_not:n + { + \protected@edef \l_@@_tmp_tl + { \l_@@_tmp_tl } + \tl_clear:N \l_@@_formatted_tl + \tl_if_empty:NF \l_@@_tmp_tl + { + \exp_after:wN \@@_format_literal_auxi:w + \l_@@_tmp_tl . + \q_recursion_tail . \q_recursion_stop + } + \exp_args:NNNV \group_end: + \tl_set:Nn \l_@@_formatted_tl + \l_@@_formatted_tl + } + } +\group_end: +% \end{macrocode} +% To introduce the font changing commands while still allowing for line +% breaks in literal units, a loop is needed to replace one |.| at a time. +% To also allow for division, a second loop is used within that to handle +% |/|: as a result, the separator between parts has to be tracked. +% \begin{macrocode} +\cs_new_protected:Npn \@@_format_literal_auxi:w #1 . + { + \quark_if_recursion_tail_stop:n {#1} + \@@_format_literal_auxii:n {#1} + \tl_set_eq:NN \l_@@_separator_tl \l_@@_product_tl + \@@_format_literal_auxi:w + } +\cs_set_protected:Npn \@@_format_literal_auxii:n #1 + { + \@@_format_literal_auxiii:w + #1 / \q_recursion_tail / \q_recursion_stop + } +\cs_new_protected:Npn \@@_format_literal_auxiii:w #1 / + { + \quark_if_recursion_tail_stop:n {#1} + \@@_format_literal_auxiv:w #1 ^ ^ \q_stop + \tl_set:Nn \l_@@_separator_tl { / } + \@@_format_literal_auxiii:w + } +% \end{macrocode} +% Within each unit any sub- and superscript parts need to be separated out: +% wrapping everything in the font command is incorrect. The superscript part +% is relatively easy as there is no catcode issue or font command to add, +% while the subscript part needs a bit more work. As the user might have the +% two parts in either order, picking up the subscript needs to look in two +% places. We assume that only one is given: odd input here is simply accepted. +% \begin{macrocode} +\use:x + { + \cs_new_protected:Npn \exp_not:N \@@_format_literal_auxiv:w + ##1 ^ ##2 ^ ##3 \exp_not:N \q_stop + { + \exp_not:N \@@_format_literal_auxv:w + ##1 + \c_@@_math_subscript_tl + \c_@@_math_subscript_tl + \exp_not:N \q_mark + ##2 + \c_@@_math_subscript_tl + \c_@@_math_subscript_tl + \exp_not:N \q_stop + } + \cs_new_protected:Npn \exp_not:N \@@_format_literal_auxv:w + ##1 \c_@@_math_subscript_tl + ##2 \c_@@_math_subscript_tl ##3 + \exp_not:N \q_mark + ##4 \c_@@_math_subscript_tl + ##5 \c_@@_math_subscript_tl ##6 + \exp_not:N \q_stop + { + \tl_set:Nx \exp_not:N \l_@@_formatted_tl + { + \exp_not:N \exp_not:V + \exp_not:N \l_@@_formatted_tl + \exp_not:N \tl_if_empty:NF + \exp_not:N \l_@@_formatted_tl + { + \exp_not:N \exp_not:V + \exp_not:N \l_@@_separator_tl + } + \exp_not:N \tl_if_blank:nF {##1} + { + \exp_not:N \exp_not:N + \exp_not:N \mathrm + { \exp_not:N \exp_not:n {##1} } + } + \exp_not:N \tl_if_blank:nF {##4} + { ^ { \exp_not:N \exp_not:n {##4} } } + \exp_not:N \tl_if_blank:nF {##2##5} + { + \c_@@_math_subscript_tl + { + \exp_not:N \exp_not:N + \exp_not:N \mathrm + { \exp_not:N \exp_not:n {##2##5} } + } + } + } + } + } +\tl_new:N \l_@@_separator_tl +% \end{macrocode} +% \end{variable} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \subsection{Parsing symbolic units} +% +% Parsing units takes place by storing information about each unit in a +% \texttt{prop}. As well as the unit itself, there are various other optional +% data points, for example a prefix or a power. Some of these can come before +% the unit, others only after. The parser therefore tracks the number of units +% read and uses the current position to allocate data to individual units. +% +% The result of parsing is a property list (\cs{l_@@_parsed_prop}) which +% contains one or more entries for each unit: +% \begin{itemize} +% \item \texttt{prefix-$n$} The symbol for the prefix which applies to this +% unit, \emph{e.g.} for \cs{kilo} with (almost certainly) would be +% |k|. +% \item \texttt{unit-$n$} The symbol for the unit itself, \emph{e.g.}~for +% \cs{metre} with (almost certainly) would be |m|. +% \item \texttt{power-$n$} The power which a unit is raised to. During +% initial parsing this will (almost certainly) be positive, but is combined +% with \texttt{per-$n$} to give a \enquote{fully qualified} power before +% any formatting takes place +% \item \texttt{per-$n$} Indicates that \texttt{per} applies to the current +% unit: stored during initial parsing then combined with \texttt{power-$n$} +% (and removed from the list) before further work. +% \item \texttt{qualifier-$n$} Any qualifier which applies to the current +% unit. +% \item \texttt{special-$n$} Any \enquote{special effect} to apply to the +% current unit. +% \end{itemize} +% +% \begin{variable}{\l_@@_sticky_per_bool} +% There is one option when \emph{parsing} the input (as opposed to +% \emph{formatting} for output): how to deal with \cs{per}. +% \begin{macrocode} +\keys_define:nn { siunitx } + { + sticky-per .bool_set:N = \l_@@_sticky_per_bool + } +% \end{macrocode} +% \end{variable} +% +% \begin{variable}{\l_@@_parsed_prop} +% \begin{variable}{\l_@@_per_bool} +% \begin{variable}{\l_@@_position_int} +% Parsing units requires a small number of variables are available: a +% \texttt{prop} for the parsed units themselves, a \texttt{bool} to +% indicate if \cs{per} is active and an \texttt{int} to track how many units +% have be parsed. +% \begin{macrocode} +\prop_new:N \l_@@_parsed_prop +\bool_new:N \l_@@_per_bool +\int_new:N \l_@@_position_int +% \end{macrocode} +% \end{variable} +% \end{variable} +% \end{variable} +% +% \begin{macro}{\@@_parse:n} +% The main parsing function is quite simple. After initialising the variables, +% each symbolic unit is set up. The input is then simply inserted into the +% input stream: the symbolic units themselves then do the real work of +% placing data into the parsing system. There is then a bit of tidying up to +% ensure that later stages can rely on the nature of the data here. +% \begin{macrocode} +\cs_new_protected:Npn \@@_parse:n #1 + { + \prop_clear:N \l_@@_parsed_prop + \bool_set_true:N \l_@@_parsing_bool + \bool_set_false:N \l_@@_per_bool + \bool_set_false:N \l_@@_test_bool + \int_zero:N \l_@@_position_int + #1 + \int_step_inline:nnnn 1 1 \l_@@_position_int + { \@@_parse_finalise:n {##1} } + \@@_parse_finalise: + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_parse_add:nnnn} +% In all cases, storing a data item requires setting a temporary \texttt{tl} +% which will be used as the key, then using this to store the value. The +% \texttt{tl} is set using \texttt{x}-type expansion as this will expand the +% unit index and any additional calculations made for this. +% \begin{macrocode} +\cs_new_protected:Npn \@@_parse_add:nnnn #1#2#3#4 + { + \tl_set:Nx \l_@@_tmp_tl { #1 - #2 } + \prop_if_in:NVTF \l_@@_parsed_prop + \l_@@_tmp_tl + { + \msg_error:nnxx { siunitx } { unit / duplicate-part } + { \exp_not:n {#1} } { \token_to_str:N #3 } + } + { + \prop_put:NVn \l_@@_parsed_prop + \l_@@_tmp_tl {#4} + } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_parse_prefix:Nn} +% \begin{macro}{\@@_parse_power:nnN} +% \begin{macro}{\@@_parse_qualifier:nn} +% \begin{macro}{\@@_parse_special:n} +% Storage of the various optional items follows broadly the same pattern +% in each case. The data to be stored is passed along with an appropriate +% key name to the underlying storage system. The details for each type of +% item should be relatively clear. For example, prefixes have to come before +% their \enquote{parent} unit and so there is some adjustment to do to add +% them to the correct unit. +% \begin{macrocode} +\cs_new_protected:Npn \@@_parse_prefix:Nn #1#2 + { + \int_set:Nn \l_@@_tmp_int { \l_@@_position_int + 1 } + \@@_parse_add:nnnn { prefix } + { \int_use:N \l_@@_tmp_int } {#1} {#2} + } +\cs_new_protected:Npn \@@_parse_power:nnN #1#2#3 + { + \tl_set:Nx \l_@@_tmp_tl + { unit- \int_use:N \l_@@_position_int } + \bool_lazy_or:nnTF + {#3} + { + \prop_if_in_p:NV + \l_@@_parsed_prop \l_@@_tmp_tl + } + { + \@@_parse_add:nnnn { power } + { + \int_eval:n + { \l_@@_position_int \bool_if:NT #3 { + 1 } } + } + {#1} {#2} + } + { + \msg_error:nnxx { siunitx } + { unit / part-before-unit } { power } { \token_to_str:N #1 } + } + } +\cs_new_protected:Npn \@@_parse_qualifier:nn #1#2 + { + \tl_set:Nx \l_@@_tmp_tl + { unit- \int_use:N \l_@@_position_int } + \prop_if_in:NVTF \l_@@_parsed_prop \l_@@_tmp_tl + { + \@@_parse_add:nnnn { qualifier } + { \int_use:N \l_@@_position_int } {#1} {#2} + } + { + \msg_error:nnnn { siunitx } + { unit / part-before-unit } { qualifier } { \token_to_str:N #1 } + } + } +% \end{macrocode} +% Special (exceptional) items should always come before the relevant units. +% \begin{macrocode} +\cs_new_protected:Npn \@@_parse_special:n #1 + { + \@@_parse_add:nnnn { special } + { \int_eval:n { \l_@@_position_int + 1 } } + {#1} {#1} + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@@_parse_unit:Nn} +% Parsing units is slightly more involved than the other cases: this is the +% one place where the tracking value is incremented. If the switch +% \cs{l_@@_per_bool} is set true then the current unit is also +% reciprocal: this can only happen if \cs{l_@@_sticky_per_bool} is also +% true, so only one test is required. +% \begin{macrocode} +\cs_new_protected:Npn \@@_parse_unit:Nn #1#2 + { + \int_incr:N \l_@@_position_int + \@@_parse_add:nnnn { unit } + { \int_use:N \l_@@_position_int } + {#1} {#2} + \bool_if:NT \l_@@_per_bool + { + \@@_parse_add:nnnn { per } + { \int_use:N \l_@@_position_int } + { \per } { true } + } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_parse_per:} +% Storing the \cs{per} command requires adding a data item separate from +% the power which applies: this makes later formatting much more +% straight-forward. This data could in principle be combined with the +% \texttt{power}, but depending on the output format required that may make +% life more complex. Thus this information is stored separately for later +% retrieval. If \cs{per} is set to be \enquote{sticky} then after parsing +% the first occurrence, any further uses are in error. +% \begin{macrocode} +\cs_new_protected:Npn \@@_parse_per: + { + \bool_if:NTF \l_@@_sticky_per_bool + { + \bool_set_true:N \l_@@_per_bool + \cs_set_protected:Npn \per + { \msg_error:nn { siunitx } { unit / duplicate-sticky-per } } + } + { + \@@_parse_add:nnnn + { per } { \int_eval:n { \l_@@_position_int + 1 } } + { \per } { true } + } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_parse_finalise:n} +% If \cs{per} applies to the current unit, the power needs to be multiplied +% by $-1$. That is done using an \texttt{fp} operation so that non-integer +% powers are supported. The flag for \cs{per} is also removed as this means +% we don't have to check that the original power was positive. To be on +% the safe side, there is a check for a trivial power at this stage. +% \begin{macrocode} +\cs_new_protected:Npn \@@_parse_finalise:n #1 + { + \tl_set:Nx \l_@@_tmp_tl { per- #1 } + \prop_if_in:NVT \l_@@_parsed_prop \l_@@_tmp_tl + { + \prop_remove:NV \l_@@_parsed_prop + \l_@@_tmp_tl + \tl_set:Nx \l_@@_tmp_tl { power- #1 } + \prop_get:NVNTF + \l_@@_parsed_prop + \l_@@_tmp_tl + \l_@@_part_tl + { + \tl_set:Nx \l_@@_part_tl + { \fp_eval:n { \l_@@_part_tl * -1 } } + \fp_compare:nNnTF \l_@@_part_tl = 1 + { + \prop_remove:NV \l_@@_parsed_prop + \l_@@_tmp_tl + } + { + \prop_put:NVV \l_@@_parsed_prop + \l_@@_tmp_tl \l_@@_part_tl + } + } + { + \prop_put:NVn \l_@@_parsed_prop + \l_@@_tmp_tl { -1 } + } + } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_parse_finalise:} +% The final task is to check that there is not a \enquote{dangling} power +% or prefix: these are added to the \enquote{next} unit so are easy to +% test for. +% \begin{macrocode} +\cs_new_protected:Npn \@@_parse_finalise: + { + \clist_map_inline:nn { per , power , prefix } + { + \tl_set:Nx \l_@@_tmp_tl + { ##1 - \int_eval:n { \l_@@_position_int + 1 } } + \prop_if_in:NVT \l_@@_parsed_prop \l_@@_tmp_tl + { \msg_error:nnn { siunitx } { unit / dangling-part } { ##1 } } + } + } +% \end{macrocode} +% \end{macro} +% +% \subsection{Formatting parsed units} +% +% \begin{variable} +% { +% \l_@@_denominator_bracket_bool , +% \l_@@_fraction_function_tl , +% \l_@@_bracket_close_tl , +% \l_@@_bracket_open_tl , +% \l_@@_parse_bool , +% \l_@@_per_symbol_tl , +% \l_@@_qualifier_mode_tl , +% \l_@@_qualifier_phrase_tl +% } +% Set up the options which apply to formatting. +% \begin{macrocode} +\keys_define:nn { siunitx } + { + bracket-denominator .bool_set:N = + \l_@@_denominator_bracket_bool , + fraction-command .tl_set:N = + \l_@@_fraction_function_tl , + parse-units .bool_set:N = + \l_@@_parse_bool , + per-mode .choice: , + per-mode / fraction .code:n = + { + \bool_set_false:N \l_@@_autofrac_bool + \bool_set_false:N \l_@@_per_symbol_bool + \bool_set_true:N \l_@@_powers_positive_bool + \bool_set_true:N \l_@@_two_part_bool + } , + per-mode / power .code:n = + { + \bool_set_false:N \l_@@_autofrac_bool + \bool_set_false:N \l_@@_per_symbol_bool + \bool_set_false:N \l_@@_powers_positive_bool + \bool_set_false:N \l_@@_two_part_bool + } , + per-mode / power-positive-first .code:n = + { + \bool_set_false:N \l_@@_autofrac_bool + \bool_set_false:N \l_@@_per_symbol_bool + \bool_set_false:N \l_@@_powers_positive_bool + \bool_set_true:N \l_@@_two_part_bool + } , + per-mode / repeated-symbol .code:n = + { + \bool_set_false:N \l_@@_autofrac_bool + \bool_set_true:N \l_@@_per_symbol_bool + \bool_set_true:N \l_@@_powers_positive_bool + \bool_set_false:N \l_@@_two_part_bool + } , + per-mode / symbol .code:n = + { + \bool_set_false:N \l_@@_autofrac_bool + \bool_set_true:N \l_@@_per_symbol_bool + \bool_set_true:N \l_@@_powers_positive_bool + \bool_set_true:N \l_@@_two_part_bool + } , + per-mode / symbol-or-fraction .code:n = + { + \bool_set_true:N \l_@@_autofrac_bool + \bool_set_true:N \l_@@_per_symbol_bool + \bool_set_true:N \l_@@_powers_positive_bool + \bool_set_true:N \l_@@_two_part_bool + } , + per-symbol .tl_set:N = + \l_@@_per_symbol_tl , + qualifier-mode .choice: , + qualifier-mode / bracket .code:n = + { \tl_set:Nn \l_@@_qualifier_mode_tl { bracket } } , + qualifier-mode / combine .code:n = + { \tl_set:Nn \l_@@_qualifier_mode_tl { combine } } , + qualifier-mode / phrase .code:n = + { \tl_set:Nn \l_@@_qualifier_mode_tl { phrase } } , + qualifier-mode / subscript .code:n = + { \tl_set:Nn \l_@@_qualifier_mode_tl { subscript } } , + qualifier-phrase .tl_set:N = + \l_@@_qualifier_phrase_tl , + unit-close-bracket .tl_set:N = + \l_@@_bracket_close_tl , + unit-open-bracket .tl_set:N = + \l_@@_bracket_open_tl + } +% \end{macrocode} +% \end{variable} +% +% \begin{variable}{\l_@@_bracket_bool} +% A flag to indicate that the unit currently under construction will require +% brackets if a power is added. +% \begin{macrocode} +\bool_new:N \l_@@_bracket_bool +% \end{macrocode} +% \end{variable} +% +% \begin{variable}{\l_@@_font_bool} +% A flag to control when font wrapping is applied to the output. +% \begin{macrocode} +\bool_new:N \l_@@_font_bool +% \end{macrocode} +% \end{variable} +% +% \begin{variable} +% { +% \l_@@_autofrac_bool , +% \l_@@_powers_positive_bool , +% \l_@@_per_symbol_bool , +% \l_@@_two_part_bool +% } +% Dealing with the various ways that reciprocal (\cs{per}) can be handled +% requires a few different switches. +% \begin{macrocode} +\bool_new:N \l_@@_autofrac_bool +\bool_new:N \l_@@_per_symbol_bool +\bool_new:N \l_@@_powers_positive_bool +\bool_new:N \l_@@_two_part_bool +% \end{macrocode} +% \end{variable} +% +% \begin{variable}{\l_@@_numerator_bool} +% Indicates that the current unit should go into the numerator when splitting +% into two parts (fractions or other \enquote{sorted} styles). +% \begin{macrocode} +\bool_new:N \l_@@_numerator_bool +% \end{macrocode} +% \end{variable} +% +% \begin{variable}{\l_@@_qualifier_mode_tl} +% For storing the text of options which are best handled by picking +% function names. +% \begin{macrocode} +\tl_new:N \l_@@_qualifier_mode_tl +% \end{macrocode} +% \end{variable} +% +% \begin{variable}{\l_@@_prefix_power_bool} +% Used to determine if prefixes are converted into powers. Note that +% while this may be set as an option \enquote{higher up}, at this point it +% is handled as an internal switch (see the two formatting interfaces for +% reasons). +% \begin{macrocode} +\bool_new:N \l_@@_prefix_power_bool +% \end{macrocode} +% \end{variable} +% +% \begin{variable}{\l_@@_prefix_fp} +% When converting prefixes to powers, the calculations are done as an +% \texttt{fp}. +% \begin{macrocode} +\fp_new:N \l_@@_prefix_fp +% \end{macrocode} +% \end{variable} +% +% \begin{variable}{\l_@@_current_tl, \l_@@_part_tl} +% Building up the (partial) formatted unit requires some token list storage. +% Each part of the unit combination that is recovered also has to be +% placed in a token list: this is a dedicated one to leave the scratch +% variables available. +% \begin{macrocode} +\tl_new:N \l_@@_current_tl +\tl_new:N \l_@@_part_tl +% \end{macrocode} +% \end{variable} +% +% \begin{variable}{\l_@@_denominator_tl} +% For fraction-like units, space is needed for the denominator as well as +% the numerator (which is handled using \cs{l_@@_formatted_tl}). +% \begin{macrocode} +\tl_new:N \l_@@_denominator_tl +% \end{macrocode} +% \end{variable} +% +% \begin{variable}{\l_@@_total_int} +% The formatting routine needs to know both the total number of units and +% the current unit. Thus an \texttt{int} is required in addition to +% \cs{l_@@_position_int}. +% \begin{macrocode} +\int_new:N \l_@@_total_int +% \end{macrocode} +% \end{variable} +% +% \begin{macro}{\@@_format_parsed:} +% \begin{macro}{\@@_format_parsed_aux:n} +% The main formatting routine is essentially a loop over each position, +% reading the various parts of the unit to build up complete unit +% combination. +% \begin{macrocode} +\cs_new_protected:Npn \@@_format_parsed: + { + \int_set_eq:NN \l_@@_total_int \l_@@_position_int + \tl_clear:N \l_@@_denominator_tl + \tl_clear:N \l_@@_formatted_tl + \fp_zero:N \l_@@_prefix_fp + \int_zero:N \l_@@_position_int + \int_do_while:nNnn + \l_@@_position_int < \l_@@_total_int + { + \bool_set_false:N \l_@@_bracket_bool + \tl_clear:N \l_@@_current_tl + \bool_set_false:N \l_@@_font_bool + \bool_set_true:N \l_@@_numerator_bool + \int_incr:N \l_@@_position_int + \clist_map_inline:nn { prefix , unit , qualifier , power , special } + { \@@_format_parsed_aux:n {##1} } + \@@_format_output: + } + \@@_format_finalise: + } +\cs_new_protected:Npn \@@_format_parsed_aux:n #1 + { + \tl_set:Nx \l_@@_tmp_tl + { #1 - \int_use:N \l_@@_position_int } + \prop_get:NVNT \l_@@_parsed_prop + \l_@@_tmp_tl \l_@@_part_tl + { \use:c { @@_format_ #1 : } } + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}[EXP]{\@@_format_bracket:N} +% A quick utility function which wraps up a token list variable in brackets +% if they are required. +% \begin{macrocode} +\cs_new:Npn \@@_format_bracket:N #1 + { + \bool_if:NTF \l_@@_bracket_bool + { + \exp_not:V \l_@@_bracket_open_tl + \exp_not:V #1 + \exp_not:V \l_@@_bracket_close_tl + } + { \exp_not:V #1 } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_format_power:} +% \begin{macro}[EXP]{\@@_format_power_aux:wTF} +% \begin{macro} +% { +% \@@_format_power_positive: , +% \@@_format_power_negative: +% } +% \begin{macro}[EXP]{\@@_format_power_negative_aux:w} +% \begin{macro}{\@@_format_power_superscript:} +% Formatting powers requires a test for negative numbers and depending on +% output format requests some adjustment to the stored value. This could be +% done using an \texttt{fp} function, but that would be slow compared to +% a dedicated if lower-level approach based on delimited arguments. +% \begin{macrocode} +\cs_new_protected:Npn \@@_format_power: + { + \@@_format_font: + \exp_after:wN \@@_format_power_aux:wTF + \l_@@_part_tl - \q_stop + { \@@_format_power_negative: } + { \@@_format_power_positive: } + } +\cs_new:Npn \@@_format_power_aux:wTF #1 - #2 \q_stop + { \tl_if_empty:nTF {#1} } +% \end{macrocode} +% In the case of positive powers, there is little to do: add the power +% as a subscript (must be required as the parser ensures it's $\neq 1$). +% \begin{macrocode} +\cs_new_protected:Npn \@@_format_power_positive: + { \@@_format_power_superscript: } +% \end{macrocode} +% Dealing with negative powers starts by flipping the switch used to track +% where in the final output the current part should get added to. For the +% case where the output is fraction-like, strip off the |~| then ensure that +% the result is not the trivial power~$1$. Assuming all is well, addition +% to the current unit combination goes ahead. +% \begin{macrocode} +\cs_new_protected:Npn \@@_format_power_negative: + { + \bool_set_false:N \l_@@_numerator_bool + \bool_if:NTF \l_@@_powers_positive_bool + { + \tl_set:Nx \l_@@_part_tl + { + \exp_after:wN \@@_format_power_negative_aux:w + \l_@@_part_tl \q_stop + } + \str_if_eq_x:nnF { \exp_not:V \l_@@_part_tl } { 1 } + { \@@_format_power_superscript: } + } + { \@@_format_power_superscript: } + } +\cs_new:Npn \@@_format_power_negative_aux:w - #1 \q_stop + { \exp_not:n {#1} } +% \end{macrocode} +% Adding the power as a superscript has the slight complication that there +% is the possibility of needing some brackets. The superscript itself uses +% \cs{sp} as that avoids any category code issues and also allows redirection +% at a higher level more readily. +% \begin{macrocode} +\cs_new_protected:Npn \@@_format_power_superscript: + { + \tl_set:Nx \l_@@_current_tl + { + \@@_format_bracket:N \l_@@_current_tl + ^ { \exp_not:V \l_@@_part_tl } + } + \bool_set_false:N \l_@@_bracket_bool + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@@_format_prefix:} +% \begin{macro}{\@@_format_prefix_power:, \@@_format_prefix_symbol:} +% Formatting for prefixes depends on whether they are to be expressed as +% symbols or collected up to be returned as a power of $10$. The latter +% case requires a bit of processing, which includes checking that the +% conversion is possible and allowing for any power that applies to the +% current unit. +% \begin{macrocode} +\cs_new_protected:Npn \@@_format_prefix: + { + \bool_if:NTF \l_@@_prefix_power_bool + { \@@_format_prefix_power: } + { \@@_format_prefix_symbol: } + } +\cs_new_protected:Npn \@@_format_prefix_power: + { + \prop_get:NVNTF \l_@@_prefixes_forward_prop + \l_@@_part_tl \l_@@_part_tl + { + \tl_set:Nx \l_@@_tmp_tl + { power- \int_use:N \l_@@_position_int } + \prop_get:NVNF \l_@@_parsed_prop + \l_@@_tmp_tl \l_@@_tmp_tl + { \tl_set:Nn \l_@@_tmp_tl { 1 } } + \fp_add:Nn \l_@@_prefix_fp + { \l_@@_tmp_tl * \l_@@_part_tl } + } + { \@@_format_prefix_symbol: } + } +\cs_new_protected:Npn \@@_format_prefix_symbol: + { \tl_set_eq:NN \l_@@_current_tl \l_@@_part_tl } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@@_format_qualifier:} +% \begin{macro} +% { +% \@@_format_qualifier_bracket : , +% \@@_format_qualifier_combine: , +% \@@_format_qualifier_phrase: , +% \@@_format_qualifier_subscript: +% } +% There are various ways that a qualifier can be added to the output. The +% idea here is to modify the \enquote{base} text appropriately and then add +% to the current unit. In the case that a linking phrase is in use, the +% addition of spaces means that the unit may end up ambiguous, and brackets +% are therefore required \emph{if} there is a power. Notice that when the +% qualifier is just treated as \enquote{text}, the auxiliary is actually +% a no-op. +% \begin{macrocode} +\cs_new_protected:Npn \@@_format_qualifier: + { + \use:c + { + @@_format_qualifier_ + \l_@@_qualifier_mode_tl : + } + \tl_put_right:NV \l_@@_current_tl \l_@@_part_tl + } +\cs_new_protected:Npn \@@_format_qualifier_bracket: + { + \@@_format_font: + \tl_set:Nx \l_@@_part_tl + { + \exp_not:V \l_@@_bracket_open_tl + \exp_not:N \mathrm + { \exp_not:V \l_@@_part_tl } + \exp_not:V \l_@@_bracket_close_tl + } + } +\cs_new_protected:Npn \@@_format_qualifier_combine: { } +\cs_new_protected:Npn \@@_format_qualifier_phrase: + { + \@@_format_font: + \tl_set:Nx \l_@@_part_tl + { + \exp_not:V \l_@@_qualifier_phrase_tl + \exp_not:N \mathrm + { \exp_not:V \l_@@_part_tl } + } + } +\cs_new_protected:Npn \@@_format_qualifier_subscript: + { + \@@_format_font: + \tl_set:Nx \l_@@_part_tl + { + \c_@@_math_subscript_tl + { + \exp_not:N \mathrm + { \exp_not:V \l_@@_part_tl } + } + } + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@@_format_special:} +% Any special odds and ends are handled by simply making the current +% combination into an argument for the recovered code. +% \begin{macrocode} +\cs_new_protected:Npn \@@_format_special: + { + \tl_set:Nx \l_@@_current_tl + { + \exp_not:V \l_@@_part_tl + { \exp_not:V \l_@@_current_tl } + } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_format_unit:} +% A very simple task: add the unit to the output currently being +% constructed. +% \begin{macrocode} +\cs_new_protected:Npn \@@_format_unit: + { + \tl_put_right:NV + \l_@@_current_tl \l_@@_part_tl + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_format_output:} +% \begin{macro} +% {\@@_format_output_aux:, \@@_format_output_denominator:} +% \begin{macro} +% { +% \@@_format_output_aux:nn , +% \@@_format_output_aux:nV , +% \@@_format_output_aux:nv +% } +% The first step here is to make a choice based on whether the current +% part should be stored as part of the numerator or denominator of a +% fraction. In all cases, if the switch \cs{l_@@_numerator_bool} is +% true then life is simple: add the current part to the numerator with +% a standard separator +% \begin{macrocode} +\cs_new_protected:Npn \@@_format_output: + { + \@@_format_font: + \bool_set_false:N \l_@@_bracket_bool + \use:c + { + @@_format_output_ + \bool_if:NTF \l_@@_numerator_bool + { aux: } + { denominator: } + } + } +\cs_new_protected:Npn \@@_format_output_aux: + { + \@@_format_output_aux:nV { formatted } + \l_@@_product_tl + } +% \end{macrocode} +% There are a few things to worry about at this stage if the current part +% is in the denominator. Powers have already been dealt with and some +% formatting outcomes only need a branch at the final point of building +% the entire unit. That means that there are three possible outcomes here: +% if collecting two separate parts, add to the denominator with a product +% separator, or if only building one token list there may be a need to use +% a symbol separator. When the |repeated-symbol| option is in use there may +% be a need to add a leading |1| to the output in the case where the +% first unit is in the denominator: that can be picked up by looking for +% empty output in combination with the flag for using a symbol in the output +% but not a two-part strategy. +% \begin{macrocode} +\cs_new_protected:Npn \@@_format_output_denominator: + { + \bool_if:NTF \l_@@_two_part_bool + { + \bool_lazy_and:nnT + { \l_@@_denominator_bracket_bool } + { ! \tl_if_empty_p:N \l_@@_denominator_tl } + { \bool_set_true:N \l_@@_bracket_bool } + \@@_format_output_aux:nV { denominator } + \l_@@_product_tl + } + { + \bool_lazy_and:nnT + { \l_@@_per_symbol_bool } + { \tl_if_empty_p:N \l_@@_formatted_tl } + { \tl_set:Nn \l_@@_formatted_tl { 1 } } + \@@_format_output_aux:nv { formatted } + { + l_@@_ + \bool_if:NTF \l_@@_per_symbol_bool + { per_symbol } + { product } + _tl + } + } + } +\cs_new_protected:Npn \@@_format_output_aux:nn #1#2 + { + \tl_set:cx { l_@@_ #1 _tl } + { + \exp_not:v { l_@@_ #1 _tl } + \tl_if_empty:cF { l_@@_ #1 _tl } + { \exp_not:n {#2} } + \exp_not:V \l_@@_current_tl + } + } +\cs_generate_variant:Nn \@@_format_output_aux:nn { nV , nv } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@@_format_font:} +% A short auxiliary which checks if the font has been applied to the +% main part of the output: if not, add it and set the flag. +% \begin{macrocode} +\cs_new_protected:Npn \@@_format_font: + { + \bool_if:NF \l_@@_font_bool + { + \tl_set:Nx \l_@@_current_tl + { + \exp_not:N \mathrm + { \exp_not:V \l_@@_current_tl } + } + \bool_set_true:N \l_@@_font_bool + } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_format_finalise:} +% \begin{macro} +% { +% \@@_format_finalise_autofrac: , +% \@@_format_finalise_fractional: , +% \@@_format_finalise_power: +% } +% Finalising the unit format is really about picking up the cases involving +% fractions: these require assembly of the parts with the need to add +% additional material in some cases +% \begin{macrocode} +\cs_new_protected:Npn \@@_format_finalise: + { + \tl_if_empty:NF \l_@@_denominator_tl + { + \bool_if:NTF \l_@@_powers_positive_bool + { \@@_format_finalise_fractional: } + { \@@_format_finalise_power: } + } + } +% \end{macrocode} +% For fraction-like output, there are three possible choices and two +% actual styles. In all cases, if the numerator is empty then it is set +% here to |1|. To deal with the \enquote{auto-format} case, the two +% styles (fraction and symbol) are handled in auxiliaries: this allows both +% to be used at the same time! Beyond that, the key here is to use a +% single \cs{tl_set:Nx} to keep down the number of assignments. +% \begin{macrocode} +\cs_new_protected:Npn \@@_format_finalise_fractional: + { + \tl_if_empty:NT \l_@@_formatted_tl + { \tl_set:Nn \l_@@_formatted_tl { 1 } } + \bool_if:NTF \l_@@_autofrac_bool + { \@@_format_finalise_autofrac: } + { + \bool_if:NTF \l_@@_per_symbol_bool + { \@@_format_finalise_symbol: } + { \@@_format_finalise_fraction: } + } + } +% \end{macrocode} +% For the \enquote{auto-selected} fraction method, the two other auxiliary +% functions are used to do both forms of formatting. So that everything +% required is available, this needs one group so that the second auxiliary +% receives the correct input. After that it is just a case of applying +% \cs{mathchoice} to the formatted output. +% \begin{macrocode} +\cs_new_protected:Npn \@@_format_finalise_autofrac: + { + \group_begin: + \@@_format_finalise_fraction: + \exp_args:NNNV \group_end: + \tl_set:Nn \l_@@_tmp_tl \l_@@_formatted_tl + \@@_format_finalise_symbol: + \tl_set:Nx \l_@@_formatted_tl + { + \mathchoice + { \exp_not:V \l_@@_tmp_tl } + { \exp_not:V \l_@@_formatted_tl } + { \exp_not:V \l_@@_formatted_tl } + { \exp_not:V \l_@@_formatted_tl } + } + } +% \end{macrocode} +% When using a fraction function the two parts are now assembled. +% \begin{macrocode} +\cs_new_protected:Npn \@@_format_finalise_fraction: + { + \tl_set:Nx \l_@@_formatted_tl + { + \exp_not:V \l_@@_fraction_function_tl + { \exp_not:V \l_@@_formatted_tl } + { \exp_not:V \l_@@_denominator_tl } + } + } +\cs_new_protected:Npn \@@_format_finalise_symbol: + { + \tl_set:Nx \l_@@_formatted_tl + { + \exp_not:V \l_@@_formatted_tl + \exp_not:V \l_@@_per_symbol_tl + \@@_format_bracket:N \l_@@_denominator_tl + } + } +% \end{macrocode} +% In the case of sorted powers, there is a test to make sure there was +% at least one positive power, and if so a simple join of the two parts +% with the appropriate product. +% \begin{macrocode} +\cs_new_protected:Npn \@@_format_finalise_power: + { + \tl_if_empty:NTF \l_@@_formatted_tl + { + \tl_set_eq:NN + \l_@@_formatted_tl + \l_@@_denominator_tl + } + { + \tl_set:Nx \l_@@_formatted_tl + { + \exp_not:V \l_@@_formatted_tl + \exp_not:V \l_@@_product_tl + \exp_not:V \l_@@_denominator_tl + } + } + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \subsection{Pre-defined unit components} +% +% Quite a number of units can be predefined: while this is a code-level module, +% there is little point having a unit parser which does not start off able to +% parse any units! +% +% \begin{macro} +% { +% \kilogram , +% \metre , +% \meter , +% \mole , +% \kelvin , +% \candela , +% \second , +% \ampere +% } +% The basic SI units: technically the correct spelling is \cs{metre} but +% US users tend to use \cs{meter}. +% \begin{macrocode} +\siunitx_declare_unit:Nn \kilogram { \kilo \gram } +\siunitx_declare_unit:Nn \metre { m } +\siunitx_declare_unit:Nn \meter { \metre } +\siunitx_declare_unit:Nn \mole { mol } +\siunitx_declare_unit:Nn \second { s } +\siunitx_declare_unit:Nn \ampere { A } +\siunitx_declare_unit:Nn \kelvin { K } +\siunitx_declare_unit:Nn \candela { cd } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\gram} +% The gram is an odd unit as it is needed for the base unit kilogram. +% \begin{macrocode} +\siunitx_declare_unit:Nn \gram { g } +% \end{macrocode} +% \end{macro} +% +% \begin{macro} +% { +% \yocto , +% \zepto , +% \atto , +% \femto , +% \pico , +% \nano , +% \micro , +% \milli , +% \centi , +% \deci +% } +% The various SI multiple prefixes are defined here: first the small +% ones. +% \begin{macrocode} +\siunitx_declare_prefix:Nnn \yocto { y } { -24 } +\siunitx_declare_prefix:Nnn \zepto { z } { -21 } +\siunitx_declare_prefix:Nnn \atto { a } { -18 } +\siunitx_declare_prefix:Nnn \femto { f } { -15 } +\siunitx_declare_prefix:Nnn \pico { p } { -12 } +\siunitx_declare_prefix:Nnn \nano { n } { -9 } +\siunitx_declare_prefix:Nnn \micro { [micro] } { -6 } +\siunitx_declare_prefix:Nnn \milli { m } { -3 } +\siunitx_declare_prefix:Nnn \centi { c } { -2 } +\siunitx_declare_prefix:Nnn \deci { d } { -1 } +% \end{macrocode} +% \end{macro} +% \begin{macro} +% { +% \deca , +% \deka , +% \hecto , +% \kilo , +% \mega , +% \giga , +% \tera , +% \peta , +% \exa , +% \zetta , +% \yotta +% } +% Now the large ones. +% \begin{macrocode} +\siunitx_declare_prefix:Nnn \deca { da } { 1 } +\siunitx_declare_prefix:Nnn \deka { da } { 1 } +\siunitx_declare_prefix:Nnn \hecto { h } { 2 } +\siunitx_declare_prefix:Nnn \kilo { k } { 3 } +\siunitx_declare_prefix:Nnn \mega { M } { 6 } +\siunitx_declare_prefix:Nnn \giga { G } { 9 } +\siunitx_declare_prefix:Nnn \tera { T } { 12 } +\siunitx_declare_prefix:Nnn \peta { P } { 15 } +\siunitx_declare_prefix:Nnn \exa { E } { 18 } +\siunitx_declare_prefix:Nnn \zetta { Z } { 21 } +\siunitx_declare_prefix:Nnn \yotta { Y } { 24 } +% \end{macrocode} +% \end{macro} +% +% \begin{macro} +% { +% \becquerel , +% \degreeCelsius , +% \coulomb , +% \farad , +% \gray , +% \hertz , +% \henry , +% \joule , +% \katal , +% \lumen , +% \lux +% } +% Named derived units: first half of alphabet. +% \begin{macrocode} +\siunitx_declare_unit:Nn \becquerel { Bq } +\siunitx_declare_unit:Nn \degreeCelsius + { \ensuremath { { } ^ { \circ } } \kern -\scriptspace C } +\siunitx_declare_unit:Nn \coulomb { C } +\siunitx_declare_unit:Nn \farad { F } +\siunitx_declare_unit:Nn \gray { Gy } +\siunitx_declare_unit:Nn \hertz { Hz } +\siunitx_declare_unit:Nn \henry { H } +\siunitx_declare_unit:Nn \joule { J } +\siunitx_declare_unit:Nn \katal { kat } +\siunitx_declare_unit:Nn \lumen { lm } +\siunitx_declare_unit:Nn \lux { lx } +% \end{macrocode} +% \end{macro} +% \begin{macro} +% { +% \newton , +% \ohm , +% \pascal , +% \radian , +% \siemens , +% \sievert , +% \steradian , +% \tesla , +% \volt , +% \watt , +% \weber +% } +% Named derived units: second half of alphabet. +% \begin{macrocode} +\siunitx_declare_unit:Nn \newton { N } +\siunitx_declare_unit:Nn \ohm { \ensuremath { \Omega } } +\siunitx_declare_unit:Nn \pascal { Pa } +\siunitx_declare_unit:Nn \radian { rad } +\siunitx_declare_unit:Nn \siemens { S } +\siunitx_declare_unit:Nn \sievert { Sv } +\siunitx_declare_unit:Nn \steradian { sr } +\siunitx_declare_unit:Nn \tesla { T } +\siunitx_declare_unit:Nn \volt { V } +\siunitx_declare_unit:Nn \watt { W } +\siunitx_declare_unit:Nn \weber { Wb } +% \end{macrocode} +% \end{macro} +% +% \begin{macro} +% { +% \day , +% \hectare , +% \hour , +% \litre , +% \liter , +% \minute , +% \tonne +% } +% Non-SI, but accepted for general use. Once again there are two +% spellings, here for litre and with different output in this case. +% \begin{macrocode} +\siunitx_declare_unit:Nn \day { d } +\siunitx_declare_unit:Nn \hectare { ha } +\siunitx_declare_unit:Nn \hour { h } +\siunitx_declare_unit:Nn \litre { L } +\siunitx_declare_unit:Nn \liter { \litre } +\siunitx_declare_unit:Nn \minute { min } +\siunitx_declare_unit:Nn \tonne { t } +% \end{macrocode} +% \end{macro} +% \begin{macro} +% { +% \arcminute , +% \arcsecond , +% \degree +% } +% Arc units: again, non-SI, but accepted for general use. +% \begin{macrocode} +\siunitx_declare_unit:Nn \arcminute { \ensuremath { ^ { \prime } } } +\siunitx_declare_unit:Nn \arcsecond { \ensuremath { ^ { \prime \prime } } } +\siunitx_declare_unit:Nn \degree { \ensuremath { ^ { \circ } } } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\astronomicalunit, \atomicmassunit, \dalton, \electronvolt} +% A few units based on physical measurements exist: these ones are accepted +% for use with the International System. +% \begin{macrocode} +\siunitx_declare_unit:Nn \astronomicalunit { au } +\siunitx_declare_unit:Nn \atomicmassunit { u } +\siunitx_declare_unit:Nn \dalton { Da } +\siunitx_declare_unit:Nn \electronvolt { eV } +% \end{macrocode} +% \end{macro} +% \begin{macro}{\nuaction, \numass, \nuspeed, \nutime} +% Natural units based on physical constants. +% \begin{macrocode} +\siunitx_declare_unit:Nn \nuaction { \ensuremath { \mathit { \hbar } } } +\siunitx_declare_unit:Nx \numass + { + \exp_not:N \ensuremath + { + \exp_not:N \mathit { m } + \c_@@_math_subscript_tl { \exp_not:N \mathrm { e } } + } + } +\siunitx_declare_unit:Nx \nuspeed + { + \exp_not:N \ensuremath + { \exp_not:N \mathit { c } \c_@@_math_subscript_tl { 0 } } + } +\siunitx_declare_unit:Nn \nutime + { \numass \per \numass \per \nuspeed \squared } +% \end{macrocode} +% \end{macro} +% \begin{macro} +% { +% \auaction , +% \aucharge , +% \auenergy , +% \aulength , +% \aumass , +% \autime , +% \bohr , +% \hartree +% } +% Atomic units based on physical constants. +% \begin{macrocode} +\siunitx_declare_unit:Nn \auaction { \ensuremath { \mathit { \hbar } } } +\siunitx_declare_unit:Nn \aucharge { \ensuremath { \mathit { e } } } +\siunitx_declare_unit:Nx \auenergy + { + \exp_not:N \ensuremath + { + \exp_not:N \mathit { E } + \c_@@_math_subscript_tl { \exp_not:N \mathrm { h } } + } + } +\siunitx_declare_unit:Nx \aulength + { + \exp_not:N \ensuremath + { \exp_not:N \mathit { a } \c_@@_math_subscript_tl { 0 } } + } +\siunitx_declare_unit:Nx \aumass + { + \exp_not:N \ensuremath + { + \exp_not:N \mathit { m } + \c_@@_math_subscript_tl { \exp_not:N \mathrm { e } } + } + } +\siunitx_declare_unit:Nn \autime { \auaction \per \auenergy } +\siunitx_declare_unit:Nn \bohr { \aulength } +\siunitx_declare_unit:Nn \hartree { \auenergy } +% \end{macrocode} +% \end{macro} +% +% \begin{macro} +% { +% \angstrom , +% \bar , +% \barn , +% \bel , +% \decibel , +% \knot , +% \millimetremercury , +% \nauticalmile , +% \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} +\siunitx_declare_unit:Nn \angstrom { \mbox { \AA } } +\siunitx_declare_unit:Nn \bar { bar } +\siunitx_declare_unit:Nn \barn { b } +\siunitx_declare_unit:Nn \bel { B } +\siunitx_declare_unit:Nn \decibel { \deci \bel } +\siunitx_declare_unit:Nn \knot { kn } +\siunitx_declare_unit:Nn \millimetremercury { mmHg } +\siunitx_declare_unit:Nn \nauticalmile { M } +\siunitx_declare_unit:Nn \neper { Np } +% \end{macrocode} +% \end{macro} +% +% \begin{macro} +% { +% \dyne , +% \erg , +% \gal , +% \gauss , +% \maxwell , +% \oersted , +% \phot , +% \poise , +% \stilb , +% \stokes +% } +% \textsc{cgs} units: similar to the set immediately above, these may be used +% for specific applications. +% \begin{macrocode} +\siunitx_declare_unit:Nn \dyne { dyn } +\siunitx_declare_unit:Nn \erg { erg } +\siunitx_declare_unit:Nn \gal { Gal } +\siunitx_declare_unit:Nn \gauss { G } +\siunitx_declare_unit:Nn \maxwell { Mx } +\siunitx_declare_unit:Nn \oersted { Oe } +\siunitx_declare_unit:Nn \phot { ph } +\siunitx_declare_unit:Nn \poise { P } +\siunitx_declare_unit:Nn \stilb { sb } +\siunitx_declare_unit:Nn \stokes { St } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\percent} +% For percent, the raw character is the most flexible way of handling output. +% \begin{macrocode} +\siunitx_declare_unit:Nn \percent { \char "25 ~ } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\square, \squared, \cubic, \cubed} +% Basic powers. +% \begin{macrocode} +\siunitx_declare_power:NNn \square \squared { 2 } +\siunitx_declare_power:NNn \cubic \cubed { 3 } +% \end{macrocode} +% \end{macro} +% +% \subsection{Messages} +% +% \begin{macrocode} +\msg_new:nnnn { siunitx } { unit / dangling-part } + { Found~#1~part~with~no~unit. } + { + Each~#1~part~must~be~associated~with~a~unit:~a~#1~part~was~found~ + but~no~following~unit~was~given. + } +\msg_new:nnnn { siunitx } { unit / duplicate-part } + { Duplicate~#1~part:~#2. } + { + Each~unit~may~have~only~one~#1:\\ + the~additional~#1~part~'#2'~will~be~ignored. + } +\msg_new:nnnn { siunitx } { unit / 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 } { unit / part-before-unit } + { Found~#1~part~before~first~unit:~#2. } + { + The~#1~part~'#2'~must~follow~after~a~unit:~ + it~cannot~appear~before~any~units~and~will~therefore~be~ignored. + } +% \end{macrocode} +% +% \subsection{Standard settings for module options} +% +% Some of these follow naturally from the point of definition +% (\emph{e.g.}~boolean variables are always |false| to begin with), +% but for clarity everything is set here. +% \begin{macrocode} +\keys_set:nn { siunitx } + { + bracket-denominator = true , + fraction-command = \frac , + parse-units = true , + per-mode = power , + per-symbol = / , + qualifier-mode = subscript , + qualifier-phrase = \ , + sticky-per = false , + unit-close-bracket = ) , % ( + unit-open-bracket = ( , % ) + unit-product = \, + } +% \end{macrocode} +% +% \begin{macrocode} +%</package> +% \end{macrocode} +% +% \end{implementation} +% +% \begin{thebibliography}{1} +% \bibitem{BIPM} +% \emph{The International System of Units (SI)}, +% \url{https://www.bipm.org/en/measurement-units/}. +% \bibitem{SI:2.1} +% \emph{SI base units}, +% \url{https://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{https://www.bipm.org/en/publications/si-brochure/section2-2-2.html}. +% \bibitem{SI:3.1} +% \emph{SI Prefixes}, +% \url{https://www.bipm.org/en/publications/si-brochure/chapter3.html}. +% \bibitem{SI:5.3.7} +% \emph{Stating values of dimensionless quantities, or quantities of +% dimension one}, +% \url{https://www.bipm.org/en/publications/si-brochure/section5-3-7.html}. +% \bibitem{SI:T6} +% \emph{Non-SI units accepted for use with the International +% System of Units}, +% \url{https://www.bipm.org/en/publications/si-brochure/table6.html}. +% \bibitem{SI:T7} +% \emph{Non-SI units whose values in SI units must be obtained +% experimentally}, +% \url{https://www.bipm.org/en/publications/si-brochure/table7.html}. +% \bibitem{SI:T8} +% \emph{Other non-SI units}, +% \url{https://www.bipm.org/en/publications/si-brochure/table8.html}. +% \bibitem{SI:T9} +% \emph{Non-SI units associated with the CGS and the CGS-Gaussian +% system of units}, +% \url{https://www.bipm.org/en/publications/si-brochure/table9.html}. +% \end{thebibliography} +% +% \PrintIndex diff --git a/Master/texmf-dist/source/latex/siunitx/siunitx-v1.dtx b/Master/texmf-dist/source/latex/siunitx/siunitx-v1.dtx new file mode 100644 index 00000000000..dade04d960c --- /dev/null +++ b/Master/texmf-dist/source/latex/siunitx/siunitx-v1.dtx @@ -0,0 +1,85 @@ +% \iffalse meta-comment +% +% File: siunitx-v1.dtx Copyright (C) 2016-2017 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 +% +% https://www.latex-project.org/lppl.txt +% +% This file is part of the "siunitx bundle" (The Work in LPPL) +% and all files in that bundle must be distributed together. +% +% The released version of this bundle is available from CTAN. +% +% ----------------------------------------------------------------------- +% +% The development version of the bundle can be found at +% +% https://github.com/josephwright/siunitx +% +% for those people who are interested. +% +% ----------------------------------------------------------------------- +% +%<*driver> +\documentclass{l3doc} +% The next line is needed so that \GetFileInfo will be able to pick up +% version data +\usepackage{siunitx} +\begin{document} + \DocInput{\jobname.dtx} +\end{document} +%</driver> +% \fi +% +% \GetFileInfo{siunitx.sty} +% +% \title{^^A +% \pkg{siunitx-v1} -- Version~1 compatibility^^A +% \thanks{This file describes \fileversion, +% last revised \filedate.}^^A +% } +% +% \author{^^A +% Joseph Wright^^A +% \thanks{^^A +% E-mail: +% \href{mailto:joseph.wright@morningstar2.co.uk} +% {joseph.wright@morningstar2.co.uk}^^A +% }^^A +% } +% +% \date{Released \filedate} +% +% \maketitle +% +% \begin{documentation} +% +% \end{documentation} +% +% \begin{implementation} +% +% \section{\pkg{siunitx-v1} implementation} +% +% Start the \pkg{DocStrip} guards. +% \begin{macrocode} +%<*cfg> +% \end{macrocode} +% +% Identify the internal prefix (\LaTeX3 \pkg{DocStrip} convention). In contrast +% to other parts of the bundle, the functions here may need to redefine those +% from various submodules. +% \begin{macrocode} +%<@@=siunitx> +% \end{macrocode} +% +% \begin{macrocode} +%</cfg> +% \end{macrocode} +% +% \end{implementation} +% +% \PrintIndex
\ No newline at end of file diff --git a/Master/texmf-dist/source/latex/siunitx/siunitx-v2.dtx b/Master/texmf-dist/source/latex/siunitx/siunitx-v2.dtx new file mode 100644 index 00000000000..7eaac797d0c --- /dev/null +++ b/Master/texmf-dist/source/latex/siunitx/siunitx-v2.dtx @@ -0,0 +1,97 @@ +% \iffalse meta-comment +% +% File: siunitx-v2.dtx Copyright (C) 2016-2017 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 +% +% https://www.latex-project.org/lppl.txt +% +% This file is part of the "siunitx bundle" (The Work in LPPL) +% and all files in that bundle must be distributed together. +% +% The released version of this bundle is available from CTAN. +% +% ----------------------------------------------------------------------- +% +% The development version of the bundle can be found at +% +% https://github.com/josephwright/siunitx +% +% for those people who are interested. +% +% ----------------------------------------------------------------------- +% +%<*driver> +\documentclass{l3doc} +% The next line is needed so that \GetFileInfo will be able to pick up +% version data +\usepackage{siunitx} +\begin{document} + \DocInput{\jobname.dtx} +\end{document} +%</driver> +% \fi +% +% \GetFileInfo{siunitx.sty} +% +% \title{^^A +% \pkg{siunitx-v2} -- Version~2 compatibility^^A +% \thanks{This file describes \fileversion, +% last revised \filedate.}^^A +% } +% +% \author{^^A +% Joseph Wright^^A +% \thanks{^^A +% E-mail: +% \href{mailto:joseph.wright@morningstar2.co.uk} +% {joseph.wright@morningstar2.co.uk}^^A +% }^^A +% } +% +% \date{Released \filedate} +% +% \maketitle +% +% \begin{documentation} +% +% \end{documentation} +% +% \begin{implementation} +% +% \section{\pkg{siunitx-v2} implementation} +% +% Start the \pkg{DocStrip} guards. +% \begin{macrocode} +%<*cfg> +% \end{macrocode} +% +% Identify the internal prefix (\LaTeX3 \pkg{DocStrip} convention). In contrast +% to other parts of the bundle, the functions here may need to redefine those +% from various submodules. +% \begin{macrocode} +%<@@=siunitx> +% \end{macrocode} +% +% The old |s| column type is handled by using the functionality of +% \pkg{collcell}. +% \begin{macrocode} +\RequirePackage { collcell } +\AtBeginDocument + { + \@@_declare_column:Nnn s + { \collectcell \unit } + { \endcollectcell } + } +% \end{macrocode} +% +% \begin{macrocode} +%</cfg> +% \end{macrocode} +% +% \end{implementation} +% +% \PrintIndex
\ No newline at end of file diff --git a/Master/texmf-dist/source/latex/siunitx/siunitx-v3.dtx b/Master/texmf-dist/source/latex/siunitx/siunitx-v3.dtx new file mode 100644 index 00000000000..615b8d00cf3 --- /dev/null +++ b/Master/texmf-dist/source/latex/siunitx/siunitx-v3.dtx @@ -0,0 +1,347 @@ +% \iffalse meta-comment +% +% File: siunitx-v3.dtx Copyright (C) 2016-2017 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 +% +% https://www.latex-project.org/lppl.txt +% +% This file is part of the "siunitx bundle" (The Work in LPPL) +% and all files in that bundle must be distributed together. +% +% The released version of this bundle is available from CTAN. +% +% ----------------------------------------------------------------------- +% +% The development version of the bundle can be found at +% +% https://github.com/josephwright/siunitx +% +% for those people who are interested. +% +% ----------------------------------------------------------------------- +% +%<*driver> +\documentclass{l3doc} +% The next line is needed so that \GetFileInfo will be able to pick up +% version data +\usepackage{siunitx} +\begin{document} + \DocInput{\jobname.dtx} +\end{document} +%</driver> +% \fi +% +% \GetFileInfo{siunitx.sty} +% +% \title{^^A +% \pkg{siunitx} -- Overall set up^^A +% \thanks{This file describes \fileversion, +% last revised \filedate.}^^A +% } +% +% \author{^^A +% Joseph Wright^^A +% \thanks{^^A +% E-mail: +% \href{mailto:joseph.wright@morningstar2.co.uk} +% {joseph.wright@morningstar2.co.uk}^^A +% }^^A +% } +% +% \date{Released \filedate} +% +% \maketitle +% +% \begin{documentation} +% +% \end{documentation} +% +% \begin{implementation} +% +% \section{\pkg{siunitx} implementation} +% +% Start the \pkg{DocStrip} guards. +% \begin{macrocode} +%<*package> +% \end{macrocode} +% +% Identify the internal prefix (\LaTeX3 \pkg{DocStrip} convention). +% \begin{macrocode} +%<@@=siunitx> +% \end{macrocode} +% +% \subsection{Initial set up} +% +% Load only the essential support (\pkg{expl3}) \enquote{up-front}. +% \begin{macrocode} +\RequirePackage{expl3} +% \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!% + }% + \endinput + }% +% \end{macrocode} +% +% Identify the package and give the over all version information. +% \begin{macrocode} +\ProvidesExplPackage {siunitx} {2017/11/26} {3.0alpha} + {A comprehensive (SI) units package} +% \end{macrocode} +% +% \subsection{Safety checks} +% +% \begin{macro}{\@@_load_check:} +% There are a number of packages that are incompatible with \pkg{siunitx} +% as they cover the same concepts and in some cases define the same command +% names. These are all tested at the point of loading to try to trap +% issues, and a couple are also tested later as it's possible for them to +% load without an obvious error if \pkg{siunitx} was loaded first. +% +% The testing here is done in a group so that the tests do not add +% anything to the hash table. +% \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} + { + \group_end: + \msg_error:nnx { siunitx } { incompatible-package } {#1} + } + { \group_end: } + } +\clist_map_function:nN + { SIunits , sistyle , unitsdef , fancyunits } + \@@_load_check:n +\AtBeginDocument + { + \clist_map_function:nN { SIunits , sistyle } + \@@_load_check:n + } +% \end{macrocode} +%\end{macro} +% +% \subsection{Top-level scratch space} +% +% \begin{macro}{\l_@@_tmp_tl} +% Scratch space for the interfaces. +% \begin{macrocode} +\tl_new:N \l_@@_tmp_tl +% \end{macrocode} +% \end{macro} +% +% \subsection{User interfaces} +% +% The user interfaces are defined in terms of documented code-level ones. +% This is all done here, and will appear in the \file{.sty} file before the +% relevant code. Things could be re-arranged by \pkg{DocStrip} but there is no +% advantage. +% +% User level interfaces are all created by \pkg{xparse} +% \begin{macrocode} +\RequirePackage { xparse } +% \end{macrocode} +% +% \subsubsection{Preamble commands} +% +% \begin{macro} +% { +% \DeclareSIPower , +% \DeclareSIPrefix , +% \DeclareSIQualifier , +% \DeclareSIUnit +% } +% Pass data to the code layer. +% \begin{macrocode} +\NewDocumentCommand \DeclareSIPower { +m +m m } + { + \siunitx_declare_power:NNn #1 #2 {#3} + } +\NewDocumentCommand \DeclareSIPrefix { +m m m } + { + \siunitx_declare_prefix:Nnn #1 {#2} {#3} + } +\NewDocumentCommand \DeclareSIQualifier { +m m } + { + \siunitx_declare_qualifier:Nn #1 {#2} + } +\NewDocumentCommand \DeclareSIUnit { O { } +m m } + { + \siunitx_declare_unit:Nn #2 {#3} + } +% \end{macrocode} +% \end{macro} +% +% \subsubsection{Document commands} +% +% \begin{macro}{\qty} +% \begin{macrocode} +\NewDocumentCommand \qty { O { } m m } + { + \leavevmode + \group_begin: + \keys_set:nn { siunitx } {#1} + \siunitx_number_format:nN {#2} \l_@@_tmp_tl + \siunitx_print:nV { number } \l_@@_tmp_tl + \, \nobreak % TEMP + \siunitx_unit_format:nN {#3} \l_@@_tmp_tl + \siunitx_print:nV { unit } \l_@@_tmp_tl + \group_end: + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\num, \unit} +% All of a standard form: start a paragraph (if required), set local +% key values, do the formatting, print the result. +% \begin{macrocode} +\NewDocumentCommand \num { O { } m } + { + \leavevmode + \group_begin: + \keys_set:nn { siunitx } {#1} + \siunitx_number_format:nN {#2} \l_@@_tmp_tl + \siunitx_print:nV { number } \l_@@_tmp_tl + \group_end: + } +\NewDocumentCommand \unit { O { } m } + { + \leavevmode + \group_begin: + \keys_set:nn { siunitx } {#1} + \siunitx_unit_format:nN {#2} \l_@@_tmp_tl + \siunitx_print:nV { unit } \l_@@_tmp_tl + \group_end: + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\sisetup} +% A very thin wrapper. +% \begin{macrocode} +\NewDocumentCommand \sisetup { m } + { \keys_set:nn { siunitx } {#1} } +% \end{macrocode} +% \end{macro} +% +% +% \subsubsection{Table column} +% +% User interfaces in tabular constructs are provided using the mechanisms from +% the \pkg{array} package. +% \begin{macrocode} +\RequirePackage { array } +% \end{macrocode} +% +% There is a slight problem with the \pkg{cellspace} package: it also uses +% \texttt{S} for a column type Here, \texttt{S} seems to make more sense for +% \pkg{siunitx}, with \texttt{C} used for \pkg{cellspace}. To enable this to +% work well, the column rewriting code happens \cs{AtBeginDocument}. The +% \texttt{S} column is deleted from \cs{NC@list} so that no warning appears. +% \begin{macrocode} +\AtBeginDocument + { + \@ifpackageloaded { cellspace } + { + \newcolumntype { C } [ 1 ] + { > { \bcolumn #1 \@nil } #1 < { \ecolumn } } + \cs_set:Npn \@@_tmp:w #1 \NC@do S #2 \q_stop + { \NC@list { #1 #2 } } + \exp_after:wN \@@_tmp:w \tex_the:D \NC@list \q_stop + \cs_undefine:N \NC@find@S + \msg_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 + } + { } + } +\msg_new:nnn { siunitx } { moved-cellspace-column } + { Column~type~for~cellspace~package~moved~to~'#1'. } +% \end{macrocode} +% +% \begin{macro}{\@@_declare_column:Nnn} +% Creating numerical columns requires that these are declared before anything +% else in \cs{NC@list}: this is necessary to work with optional arguments. +% This means a bit of manual effort after the simple declaration of a new +% column type. The token assigned to the column type is not fixed as this +% allows the same code to be used in compatibility with version~$2$. +% \begin{macrocode} +\cs_new_protected:Npn \@@_declare_column:Nnn #1#2#3 + { + \newcolumntype {#1} { } + \cs_set_protected:Npn \@@_tmp:w \NC@do ##1##2 \NC@do #1 + { \NC@list { \NC@do ##1 \NC@do #1 ##2 } } + \exp_after:wN \@@_tmp:w \tex_the:D \NC@list + \exp_args:NNc \renewcommand * { NC@rewrite@ #1 } [ 1 ] [ ] + { + \@temptokena \expandafter + { + \the \@temptokena + > {#2} c < {#3} + } + \NC@find + } + } +% \end{macrocode} +% When \pkg{mdwtab} is loaded the syntax required is slightly different. +% \begin{macrocode} +\AtBeginDocument + { + \@ifpackageloaded { mdwtab } + { + \cs_set_protected:Npn \@@_declare_column:Nnn #1#2#3 + { + \newcolumntype {#1} [ 1 ] [ ] + { > {#2} c < {#3} } + } + } + { } + } +\AtBeginDocument + { + \@@_declare_column:Nnn n + { + \keys_set:nn { siunitx } {#1} + \siunitx_cell_begin: + } + { \siunitx_cell_end: } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macrocode} +%</package> +% \end{macrocode} +% +% \end{implementation} +% +% \PrintIndex diff --git a/Master/texmf-dist/source/latex/siunitx/siunitx.dtx b/Master/texmf-dist/source/latex/siunitx/siunitx.dtx index 608a49f3764..9fcf307dceb 100644 --- a/Master/texmf-dist/source/latex/siunitx/siunitx.dtx +++ b/Master/texmf-dist/source/latex/siunitx/siunitx.dtx @@ -76,7 +76,7 @@ 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 +See https://www.latex-project.org/lppl.txt --------------------------------------------------------------- \endpreamble @@ -88,7 +88,7 @@ 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 + https://www.latex-project.org/lppl.txt This work is "maintained" (as per LPPL maintenance status) by Joseph Wright. @@ -670,6 +670,8 @@ This work consists of the file siunitx.dtx % \changes{v2.7i}{2017/07/23}{Rename an incorrect variable} % \changes{v2.7k}{2017/11/01}{Fix issues when units are not parsed} % \changes{v2.7l}{2018/03/11}{Track \pkg{unicode-math} changes} +% \changes{v2.7n}{2018/04/27}{Fix issue with symbolic input +% and digit grouping} % %\begin{abstract} % Physical quantities have both numbers and units, and each physical @@ -5218,7 +5220,7 @@ This work consists of the file siunitx.dtx % % The usual preliminaries. % \begin{macrocode} -\ProvidesExplPackage {siunitx} {2018-03-20} {2.7m} +\ProvidesExplPackage {siunitx} {2018-04-27} {2.7n} {A comprehensive (SI) units package} % \end{macrocode} % @@ -7263,7 +7265,7 @@ This work consists of the file siunitx.dtx { \prop_put:Nnn \l_@@_number_in_prop { symbolic } { true } - \@@_number_in_digit:n { \ensuremath {#1} } + \@@_number_in_digit:n {#1} } { \tl_if_in:NnF \l_@@_input_ignore_tl {#1} diff --git a/Master/texmf-dist/source/latex/siunitx/siunitx.ins b/Master/texmf-dist/source/latex/siunitx/siunitx.ins new file mode 100644 index 00000000000..d5e07966fb5 --- /dev/null +++ b/Master/texmf-dist/source/latex/siunitx/siunitx.ins @@ -0,0 +1,83 @@ +\iffalse meta-comment + +File: siunitx.ins Copyright (C) 2014-2017 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 + + https://www.latex-project.org/lppl.txt + +This file is part of the "siunitx bundle" (The Work in LPPL) +and all files in that bundle must be distributed together. + +The released version of this bundle is available from CTAN. + +----------------------------------------------------------------------- + +The development version of the bundle can be found at + + https://github.com/josephwright/siunitx + +for those people who are interested. + +----------------------------------------------------------------------- + +\fi + +\input l3docstrip.tex +\askforoverwritefalse + +% stop DocStrip adding rather wordy text +\preamble +\endpreamble +\postamble +Copyright (C) 2008-2017 by + Joseph Wright <joseph.wright@morningstar2.co.uk> + +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: + + https://www.latex-project.org/lppl.txt + +This work is "maintained" (as per LPPL maintenance status) by + Joseph Wright. + +This work consists of the files siunitx.dtx, + siunitx.ins, + siunitx-v3.dtx, + siunitx-angle.dtx, + siunitx-number.dtx, + siunitx-print.dtx, + siunitx-table.dtx, + siunitx-unit.dtx, + siunitx-v1.dtx and + siunitx-v2.dtx, + and the derived files siunitx.pdf, + siunitx.sty, + siunitx-v1.cfg and + siunitx-v2.cfg. + +\endpostamble + +\keepsilent + +\generate + {% + \file{siunitx.sty} + {% + \from{siunitx-v3.dtx} {package} + \from{siunitx-angle.dtx} {package} + \from{siunitx-number.dtx}{package} + \from{siunitx-print.dtx} {package} + \from{siunitx-table.dtx} {package} + \from{siunitx-unit.dtx} {package} + }% + \file{siunitx-v2.cfg} + {\from{siunitx-v2.dtx}{cfg}}% + } + +\endbatchfile |