diff options
author | Karl Berry <karl@freefriends.org> | 2018-05-03 21:02:51 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2018-05-03 21:02:51 +0000 |
commit | 3bdba37dd5619bcbc46b0e684507cbb0f661eb8b (patch) | |
tree | badcc270fdf874e08aa0fe7a85048a5037cef25a /Master/texmf-dist/source/latex/siunitx/siunitx-number.dtx | |
parent | 43cc6b933ec42794dc802aed3ef8ca8dbec6c70e (diff) |
siunitx (3may18)
git-svn-id: svn://tug.org/texlive/trunk@47596 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/source/latex/siunitx/siunitx-number.dtx')
-rw-r--r-- | Master/texmf-dist/source/latex/siunitx/siunitx-number.dtx | 1862 |
1 files changed, 0 insertions, 1862 deletions
diff --git a/Master/texmf-dist/source/latex/siunitx/siunitx-number.dtx b/Master/texmf-dist/source/latex/siunitx/siunitx-number.dtx deleted file mode 100644 index 63de999adce..00000000000 --- a/Master/texmf-dist/source/latex/siunitx/siunitx-number.dtx +++ /dev/null @@ -1,1862 +0,0 @@ -% \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 |