summaryrefslogtreecommitdiff
path: root/macros/latex/contrib/siunitx/siunitx-number.dtx
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2022-04-26 03:02:04 +0000
committerNorbert Preining <norbert@preining.info>2022-04-26 03:02:04 +0000
commit6f7554fc6cab67e3dc397ce7a942889eedbc4967 (patch)
treecd63f9ed43b147e44b3f1981bf7bda23680416b1 /macros/latex/contrib/siunitx/siunitx-number.dtx
parent4688b855bb6f8b817901a7c777e8aecd1a189622 (diff)
CTAN sync 202204260302
Diffstat (limited to 'macros/latex/contrib/siunitx/siunitx-number.dtx')
-rw-r--r--macros/latex/contrib/siunitx/siunitx-number.dtx1304
1 files changed, 931 insertions, 373 deletions
diff --git a/macros/latex/contrib/siunitx/siunitx-number.dtx b/macros/latex/contrib/siunitx/siunitx-number.dtx
index 4f3708e706..f64fb85192 100644
--- a/macros/latex/contrib/siunitx/siunitx-number.dtx
+++ b/macros/latex/contrib/siunitx/siunitx-number.dtx
@@ -100,7 +100,14 @@
% Valid uncertainty \meta{identifiers} currently are
% \begin{itemize}
% \item[\texttt{S}] A single symmetrical uncertainty (\foreign{e.g.}~a
-% statistical standard uncertainty)
+% statistical standard uncertainty). The data item here is a single
+% value representing the uncertainty in the least-significant digits
+% \item[\texttt{A}] A single unsymmetrical uncertainty. The data item here
+% contains two brace groups, each using the same least-significant digit
+% approach as the \texttt{S} type. The positive component is given first
+% and the negative second, and neither has a sign.
+% \item A combination of \texttt{S} and \texttt{A} entries, with one data
+% item per entry. These are then iterated over to be output in order.
% \end{itemize}
% If a decimal marker should be explicitly recorded as present for a value
% with no decimal digits, the \meta{decimal} part should contain
@@ -301,22 +308,42 @@
% \end{syntax}
% \end{function}
%
+% \begin{function}
+% {digit-group-size, digit-group-first-size, digit-group-other-size}
+% \begin{syntax}
+% |digit-group-number| = \meta{integer}
+% \end{syntax}
+% Sets the size of the block (the number of digits) used when grouping
+% digits. The option |digit-group-first-size| applies to the first grouping,
+% \foreign{i.e.}~immediately next to the decimal marker, while
+% |digit-group-other-size| applies to all other groups. Both can be set
+% using |digit-group-size|. The standard setting for both options is $3$.
+% \end{function}
+%
% \begin{function}{group-digits}
% \begin{syntax}
% |group-digits| = |all|\verb"|"|decimal|\verb"|"|integer|\verb"|"|none|
% \end{syntax}
+% Choice to specify whether digits in a number are grouped. The option |none|
+% entirely disables this, while |all| means that both the integer and decimal
+% parts are grouped. The settings |integer| and |decimal| activate grouping
+% for the relevant part only. The standard setting is |all|.
% \end{function}
%
% \begin{function}{group-minimum-digits}
% \begin{syntax}
% |group-minimum-digits| = \meta{value}
% \end{syntax}
+% The number of digits that must be present in a numerical part (integer or
+% decimal) before digit grouping is attempted. The standard setting is $4$.
% \end{function}
%
% \begin{function}{group-separator}
% \begin{syntax}
% |group-separator| = \meta{symbol}
% \end{syntax}
+% Sets the symbol inserted between groups of digits. The standard setting is
+% a thin space (\cs{,}).
% \end{function}
%
% \begin{function}{input-close-uncertainty}
@@ -443,48 +470,96 @@
% \begin{syntax}
% |retain-explicit-plus| = |true|\verb"|"|false|
% \end{syntax}
+% Switch which determines if an explicit |+| is retained as a sign when
+% parsing. The standard setting is |false|.
% \end{function}
%
% \begin{function}{retain-explicit-decimal-marker}
% \begin{syntax}
% |retain-explicit-decimal-marker| = |true|\verb"|"|false|
% \end{syntax}
+% Switch which determines if an explicit decimal marker is retained when
+% parsing a number where there is no decimal part to a number
+% (\foreign{i.e.}~whether to differentiate |10| and |10.|). The standard
+% setting is |false|.
+% \end{function}
+%
+% \begin{function}{retain-negative-zero}
+% \begin{syntax}
+% |retain-negative-zero| = |true|\verb"|"|false|
+% \end{syntax}
+% Switch which determines if a negative sign is retained where the value of
+% a parsed number is exactly zero. The standard setting is |false|.
% \end{function}
%
% \begin{function}{retain-zero-uncertainty}
% \begin{syntax}
% |retain-zero-uncertainty| = |true|\verb"|"|false|
% \end{syntax}
+% Switch which determines if an entirely zero uncertainty part is retained
+% on parsing, or whether this is normalised to remove the uncertainty.
+% The standard setting is |false|.
% \end{function}
%
% \begin{function}{round-half}
% \begin{syntax}
% |round-half| = |even|\verb"|"|up|
% \end{syntax}
+% Choice which determines how values of exactly half are rounded. The setting
+% |up| means that the value is always rounded away from zero, whereas the
+% setting |even| means that the value will be rounded to the closes even
+% number. The standard setting is |up|.
% \end{function}
%
% \begin{function}{round-minimum}
% \begin{syntax}
% |round-minimum| = \meta{min}
% \end{syntax}
+% Literal which sets a minimum value below which rounded values will be
+% replaced by this value and a |>| or |<|, as appropriate for the sign of
+% the value. The standard setting is empty, \foreign{i.e.}~there is no
+% minimum.
% \end{function}
%
% \begin{function}{round-mode}
% \begin{syntax}
% |round-mode| = |figures|\verb"|"|none|\verb"|"|places|\verb"|"|uncertainty|
% \end{syntax}
+% Choice which specifies the rounding approach used for numbers. The choice
+% |figures| means that values are rounding to the number of significant
+% figures specified by |round-precision|. The setting |places| rounds to
+% |round-precision| interpreted as a number of decimal places: this may be
+% negative (rounding to an integer). The setting |none| disables rounding.
+% The setting |uncertainty| first rounds the uncertainty to the number of
+% significant figures specified by |round-precision|, then rounds the main
+% value such that its accuracy is correctly specified by this updated
+% uncertainty. The standard setting is |none|.
% \end{function}
%
% \begin{function}{round-pad}
% \begin{syntax}
% |round-pad| = |true|\verb"|"|false|
% \end{syntax}
+% Switch which specifies if values should be padded to the required number
+% length when rounding to a number of decimal places. The standard setting is
+% |true|.
% \end{function}
%
% \begin{function}{round-precision}
% \begin{syntax}
% |round-precision| = \meta{precision}
% \end{syntax}
+% Integer specifying the number of digits used as a target when rounding:
+% this may be interpreted as decimal places or significant figures,
+% depending on active |round-mode|. The standard setting is $2$.
+% \end{function}
+%
+% \begin{function}{round-zero-positive}
+% \begin{syntax}
+% |round-zero-positive| = |true|\verb"|"|false|
+% \end{syntax}
+% Switch to control whether a value rounded to zero is regarded as a positive
+% number if the input was negative. The standard setting is |true|.
% \end{function}
%
% \begin{function}{tight-spacing}
@@ -493,16 +568,74 @@
% \end{syntax}
% \end{function}
%
+% \begin{function}{uncertainty-descriptor-mode}
+% \begin{syntax}
+% |uncertainty-descriptor| = |bracket|\verb"|"|bracket-separator|\verb"|"|separator|\verb"|"|subscript|
+% \end{syntax}
+% Selects how uncertainty descriptors are formatted: a choice from the
+% options |bracket|, |text| and |subscript|. The option |bracket| wraps the
+% descriptor in parenthesis, |bracket-separator| does the same but also
+% includes a separator between the uncertainty and opening bracket,
+% |separator| places the descriptor after the uncertainty and a separator,
+% and |subscript| formats the descriptor as a subscript. The
+% standard setting is |bracket-separator|.
+% \end{function}
+%
+% \begin{function}{uncertainty-descriptor-separator}
+% \begin{syntax}
+% |uncertainty-descriptor-separator| = \meta{separator}
+% \end{syntax}
+% Separateor inserted between the uncertainty and descriptor when one is
+% required by |uncertainty-separator-mode|. The standard setting is
+% \verb*|\ |.
+% \end{function}
+%
+% \begin{function}{uncertainty-descriptors}
+% \begin{syntax}
+% |uncertainty-descriptors| = \meta{clist}
+% \end{syntax}
+% Stores the list of descriptors used when there are multiple uncertainty
+% components given. This is not used when there is only a single uncertainty
+% component present. The standard setting is |empty|.
+% \end{function}
+%
% \begin{function}{uncertainty-mode}
% \begin{syntax}
% |uncertainty-mode| = |compact|\verb"|"|compact-marker|\verb"|"|full|\verb"|"|separate|
% \end{syntax}
+% Switch to determine how single symmetrical uncertainties are formatted.
+% When this is set to |separate|, the uncertainty is printed as an entirely
+% separate number preceded by \cs{pm}. Other settings all place the
+% uncertainty in parentheses directly attached to the main value. The
+% standard setting of |compact| prints digits of uncertainty in the
+% least-significant digits. It does \emph{not} print a decimal marker if the
+% uncertainty crosses the decimal. The setting |full| prints the full value
+% of the uncertainty. The setting |compact-marker| is available to print in the
+% |compact| style except where the uncertainty crosses the decimal, in which case the
+% |full| style is used. The standard setting is |compact|.
% \end{function}
%
% \begin{function}{uncertainty-separator}
% \begin{syntax}
% |uncertainty-separator| = \meta{separator}
% \end{syntax}
+% Stores the separator used between the main value and uncertainty when using
+% the |compact| or |compact-marker| style setting for |uncertainty-mode|.
+% \end{function}
+%
+% \begin{function}{zero-decimal-as-symbol}
+% \begin{syntax}
+% |zero-decimal-as-symbol| = |true|\verb"|"|false|
+% \end{syntax}
+% Switch to determine if an entirely zero decimal part is replaced by a
+% symbol. Does not apply if the decimal part is marked as entirely absent.
+% \end{function}
+%
+% \begin{function}{zero-symbol}
+% \begin{syntax}
+% |zero-symbol| = \meta{symbol}
+% \end{syntax}
+% Material printed when a zero numerical component is replaced by a symbol.
% \end{function}
%
% \end{documentation}
@@ -646,6 +779,7 @@
% \l_@@_input_uncert_sign_tl ,
% \l_@@_explicit_decimal_bool ,
% \l_@@_explicit_plus_bool ,
+% \l_@@_negative_zero_bool ,
% \l_@@_zero_uncert_bool
% }
% \begin{macro}[EXP]{\@@_expression:n}
@@ -688,6 +822,8 @@
\l_@@_explicit_decimal_bool ,
retain-explicit-plus .bool_set:N =
\l_@@_explicit_plus_bool ,
+ retain-negative-zero .bool_set:N =
+ \l_@@_negative_zero_bool ,
retain-zero-uncertainty .bool_set:N =
\l_@@_zero_uncert_bool
}
@@ -753,6 +889,14 @@
% \end{macrocode}
% \end{variable}
%
+% \begin{variable}{\l_@@_uncert_tl}
+% To allow multiple uncertainties, we want to build this up as possibly
+% multiple entries.
+% \begin{macrocode}
+\tl_new:N \l_@@_uncert_tl
+% \end{macrocode}
+% \end{variable}
+%
% \begin{variable}{\l_@@_validate_bool}
% Used to set up for validation with no error production.
% \begin{macrocode}
@@ -825,6 +969,7 @@
{
\group_begin:
\tl_clear:N \l_@@_parsed_tl
+ \tl_clear:N \l_@@_uncert_tl
\tl_map_inline:Nn \l_@@_input_ignore_tl
{
\token_if_macro:NT ##1
@@ -858,25 +1003,11 @@
% \begin{macrocode}
\cs_new_protected:Npn \@@_parse_check:
{
- \tl_if_empty:NF \l_@@_flex_tl
+ \tl_put_right:NV \l_@@_uncert_tl \l_@@_flex_tl
+ \tl_if_empty:NF \l_@@_uncert_tl
{
- \bool_lazy_and:nnTF
- {
- \tl_if_blank_p:f
- { \exp_after:wN \use_iv:nnnn \l_@@_parsed_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_@@_parsed_tl }
- }
+ \tl_if_blank:fTF { \exp_after:wN \use_iv:nnnn \l_@@_parsed_tl }
+ { \@@_parse_combine_uncert: }
{ \tl_clear:N \l_@@_parsed_tl }
}
\tl_if_empty:NTF \l_@@_parsed_tl
@@ -893,111 +1024,159 @@
% \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}
+% \begin{macro}[EXP]{\@@_parse_combine_uncert:nnnn}
+% \begin{macro}[EXP]{\@@_parse_combine_uncert:nn}
+% \begin{macro}[EXP]{\@@_parse_combine_uncert_loop:nnnnnnn}
+% \begin{macro}[EXP]{\@@_parse_combine_uncert:nnnnnn}
+% \begin{macro}[EXP]{\@@_parse_combine_uncert:nnnnnnn}
+% \begin{macro}[EXP]{\@@_parse_combine_uncert:nnnnn}
+% \begin{macro}[EXP]{\@@_parse_combine_uncert_aux:nnnn}
+% \begin{macro}[EXP]{\@@_parse_combine_uncert:N}
+% \begin{macro}[EXP]{\@@_parse_combine_uncert:w}
+% \begin{macro}[EXP]{\@@_parse_combine_uncert_end:nnn}
+% \begin{macro}[EXP]{\@@_parse_combine_uncert_end:nnnn}
% 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.
+% stores: the sign, integer and decimal parts from the real number. Then
+% set up a loop to deal with each uncertainty to combine. Everything is done
+% by expansion to avoid repeated assignments. To allow for the case where
+% there is an error, the setup doesn't insert any tokens until the end of
+% the loop, which means a bit of work on the stack.
% \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_@@_parsed_tl \l_@@_flex_tl
+ \tl_set:Nx \l_@@_parsed_tl
+ {
+ \exp_after:wN \@@_parse_combine_uncert:nnnn
+ \l_@@_parsed_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_@@_parsed_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.
+% Here, |#1| and |#2| are not required at this stage, while |#4| is junk.
+% Thus |#3| is the only item needed for the rest of the process. After a
+% little argument shuffling, the main loop can begin.
% \begin{macrocode}
-\cs_new_protected:Npn
- \@@_parse_combine_uncert_auxi:nnnnnnnn #1#2#3#4#5#6#7#8
+\cs_new:Npn \@@_parse_combine_uncert:nnnn #1#2#3#4
+ {
+ \exp_after:wN \@@_parse_combine_uncert:nn
+ \exp_after:wN { \l_@@_uncert_tl } {#3}
+ }
+\cs_new:Npn \@@_parse_combine_uncert:nn #1#2
{
- \@@_parse_combine_uncert_auxii:fnnnn
- { \int_eval:n { \tl_count:n {#3} - \tl_count:n {#7} } }
- {#2} {#3} {#6} {#7}
+ \@@_parse_combine_uncert_loop:nnnnnnn {#2} { } { }
+ #1
+ { \q_recursion_tail } { } { } { } \q_recursion_stop
}
-\cs_new_protected:Npn
- \@@_parse_combine_uncert_auxii:nnnnn #1
+% \end{macrocode}
+% Here, |#4| and |#7| are junk arguments simply there to mop up
+% tokens, with the exception that |#4| is also used for the end-of-loop
+% test.
+% \begin{macrocode}
+\cs_new:Npn \@@_parse_combine_uncert_loop:nnnnnnn #1#2#3#4#5#6#7
{
- \@@_parse_combine_uncert_auxiii:fnnnnn
+ \quark_if_recursion_tail_stop_do:nn {#4}
+ { \@@_parse_combine_uncert_end:nnn {#1} {#2} {#3} }
+ \exp_args:Nf \@@_parse_combine_uncert:nnnnnn
+ { \int_eval:n { \tl_count:n {#1} - \tl_count:n {#6} } }
+ {#1} {#2} {#3} {#5} {#6}
+ }
+% \end{macrocode}
+% 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.
+% \begin{macrocode}
+\cs_new:Npn \@@_parse_combine_uncert:nnnnnn #1
+ {
+ \exp_args:Nf \@@_parse_combine_uncert:nnnnnnn
{ \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
+\cs_new:Npn \@@_parse_combine_uncert:nnnnnnn #1#2#3#4#5#6#7
{
\int_compare:nNnTF {#2} > 0
{
- \@@_parse_combine_uncert_auxiv:nnnn
- {#3} {#4} {#5} { #6 #1 }
+ \@@_parse_combine_uncert:nnnnn
+ {#3} {#4} {#5} {#6} { #7 #1 }
}
{
- \@@_parse_combine_uncert_auxiv:nnnn
- {#3} { #4 #1 } {#5} {#6}
+ \@@_parse_combine_uncert:nnnnn
+ { #3 #1 } {#4} {#5} {#6} {#7}
}
}
-\cs_generate_variant:Nn
- \@@_parse_combine_uncert_auxiii:nnnnnn { f }
-\cs_new_protected:Npn
- \@@_parse_combine_uncert_auxiv:nnnn #1#2#3#4
+% \end{macrocode}
+% We now ensure that the decimal part is never entirely blank \emph{if} there
+% are decimal-part uncertainty digits. There is also a need to handle the
+% possibly of an entirely empty uncertainty, where the value is zero and that
+% is not being retained.
+% \begin{macrocode}
+\cs_new:Npn \@@_parse_combine_uncert:nnnnn #1#2#3#4#5
{
- \tl_set:Nx \l_@@_parsed_tl
+ \exp_args:Nee \@@_parse_combine_uncert_aux:nnnn
{
- { \tl_head:V \l_@@_parsed_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
- }
+ \bool_lazy_and:nnTF
+ { \tl_if_blank_p:n {#1} }
+ { ! \tl_if_blank_p:n {#5} }
+ { 0 }
+ { \exp_not:n {#1} }
+ }
+ {
+ \@@_parse_combine_uncert:N #4#5
+ \q_recursion_tail \q_recursion_stop
+ }
+ {#2}
+ {#3}
+ }
+\cs_new:Npn \@@_parse_combine_uncert_aux:nnnn #1#2#3#4
+ {
+ \exp_args:Neee \@@_parse_combine_uncert_loop:nnnnnnn
+ { \exp_not:n {#1} }
+ {
+ \exp_not:n {#3}
+ \tl_if_blank:nF {#2} { S }
+ }
+ {
+ \exp_not:n {#4}
+ \tl_if_blank:nF {#2} { { \exp_not:n {#2} } }
}
}
% \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
+\cs_new:Npn \@@_parse_combine_uncert:N #1
{
\quark_if_recursion_tail_stop_do:Nn #1
- {
- \bool_if:NT \l_@@_zero_uncert_bool
- { { S } { 0 } }
- }
+ { \bool_if:NT \l_@@_zero_uncert_bool { 0 } }
\str_if_eq:nnTF {#1} { 0 }
- { \@@_parse_combine_uncert_auxv:w }
- { \@@_parse_combine_uncert_auxvi:w #1 }
+ { \@@_parse_combine_uncert:N }
+ { \@@_parse_combine_uncert:w #1 }
}
-\cs_new:Npn \@@_parse_combine_uncert_auxvi:w
+\cs_new:Npn \@@_parse_combine_uncert:w
#1 \q_recursion_tail \q_recursion_stop
- { { S } { \exp_not:n {#1} } }
+ { \exp_not:n {#1} }
% \end{macrocode}
+% Recover the sign and integer part, then add in the new decimal and the
+% uncertainties.
+% \begin{macrocode}
+\cs_new:Npn \@@_parse_combine_uncert_end:nnn #1#2#3
+ {
+ \exp_after:wN \@@_parse_combine_uncert_end:nnnn
+ \l_@@_parsed_tl
+ { \exp_not:n {#1} }
+ {
+ \tl_if_blank:nF {#2}
+ { \exp_not:n { {#2} #3 } }
+ }
+ }
+\cs_new:Npn \@@_parse_combine_uncert_end:nnnn #1#2#3#4
+ { \exp_not:n { {#1} {#2} } }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
@@ -1155,9 +1334,10 @@
% \end{macro}
%
% \begin{macro}{\@@_parse_finalise:}
-% \begin{macro}{\@@_parse_finalise:nw}
-% Combine all of the bits of a number together: both the real and
-% imaginary parts contain all of the data.
+% \begin{macro}[EXP]{\@@_parse_finalise:nnnn}
+% \begin{macro}[EXP]{\@@_parse_finalise:nw}
+% Combine all of the bits of a number together, dealing with negative zero
+% if required.
% \begin{macrocode}
\cs_new_protected:Npn \@@_parse_finalise:
{
@@ -1166,12 +1346,28 @@
\tl_set:Nx \l_@@_parsed_tl
{
{ \exp_not:V \l_@@_comparator_tl }
- \exp_not:V \l_@@_parsed_tl
+ \exp_after:wN \@@_parse_finalise:nnnn \l_@@_parsed_tl
\exp_after:wN \@@_parse_finalise:nw
\l_@@_exponent_tl \q_stop
}
}
}
+\cs_new:Npn \@@_parse_finalise:nnnn #1#2#3#4
+ {
+ \bool_lazy_all:nTF
+ {
+ { ! \l_@@_negative_zero_bool }
+ { \str_if_eq_p:nn {#1} { - } }
+ { ! \tl_if_blank_p:n {#2#3} }
+ {
+ \str_if_eq_p:ee
+ { \exp_not:n {#2#3} }
+ { \prg_replicate:nn { \tl_count:n {#2#3} } { 0 } }
+ }
+ }
+ { \exp_not:n { { } {#2} {#3} {#4} } }
+ { \exp_not:n { {#1} {#2} {#3} {#4} } }
+ }
\cs_new:Npn \@@_parse_finalise:nw #1#2 \q_stop
{
{ \exp_not:n {#1} }
@@ -1180,21 +1376,21 @@
% \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_first:NNN}
+% \begin{macro}{\@@_parse_loop_main:NNNN}
% \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_digit:NNNN}
+% \begin{macro}{\@@_parse_loop_main_decimal:N}
+% \begin{macro}{\@@_parse_loop_main_uncert:NN}
% \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_root_swap:NNwNN}
-% \begin{macro}{\@@_parse_loop_break:wN}
+% \begin{macro}{\@@_parse_loop_after_decimal:NN}
+% \begin{macro}{\@@_parse_loop_break:w}
% At this stage, the partial input \cs{l_@@_arg_tl} will contain any
-% mantissa, which may contain an uncertainty or complex part. Parsing this
+% mantissa, which may contain one or more uncertainties. 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
@@ -1229,25 +1425,25 @@
{
\bool_if:NTF #2
{ \tl_put_right:Nn #1 { { } { } { } } }
- { \@@_parse_loop_break:wN \q_recursion_stop }
+ { \@@_parse_loop_break:w \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
+ \@@_parse_loop_main:NNNN
+ #1 \c_true_bool \c_false_bool #3
}
{
\tl_if_in:NnTF \l_siunitx_number_input_decimal_tl {#3}
{
\tl_put_right:Nn #1 { { 0 } }
- \@@_parse_loop_after_decimal:NNN #1 #2
+ \@@_parse_loop_after_decimal:NN #1
}
- { \@@_parse_loop_break:wN }
+ { \@@_parse_loop_break:w }
}
}
% \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
+% finding the main 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,
@@ -1264,37 +1460,33 @@
% there leading to a store-and-switch situation.
% \item An open-uncertainty token: switch to the dedicated collector
% for uncertainties.
-% \item A sign token (if allowed): stop collecting this number and
-% restart collection for the second part.
+% \item A sign token: stop collecting this number and
+% restart collection for the next part.
% \end{itemize}
% \begin{macrocode}
-\cs_new_protected:Npn \@@_parse_loop_main:NNNNN #1#2#3#4#5
+\cs_new_protected:Npn \@@_parse_loop_main:NNNN #1#2#3#4
{
- \quark_if_recursion_tail_stop_do:Nn #5
+ \quark_if_recursion_tail_stop_do:Nn #4
{ \@@_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_digit_tl {#4}
+ { \@@_parse_loop_main_digit:NNNN #1#2#3#4 }
{
- \tl_if_in:NnTF \l_siunitx_number_input_decimal_tl {#5}
+ \tl_if_in:NnTF \l_siunitx_number_input_decimal_tl {#4}
{
\bool_if:NTF #2
- { \@@_parse_loop_main_decimal:NN #1 #4 }
- { \@@_parse_loop_break:wN }
+ { \@@_parse_loop_main_decimal:N #1 }
+ { \@@_parse_loop_break:w }
}
{
- \tl_if_in:NnTF \l_@@_input_uncert_open_tl {#5}
- { \@@_parse_loop_main_uncert:NNN #1#2 #4 }
+ \tl_if_in:NnTF \l_@@_input_uncert_open_tl {#4}
+ { \@@_parse_loop_main_uncert:NN #1 #2 }
{
- \bool_if:NTF #4
+ \tl_if_in:NnTF \l_@@_input_uncert_sign_tl {#4}
{
- \tl_if_in:NnTF \l_siunitx_number_input_sign_tl {#5}
- {
- \@@_parse_loop_main_sign:NNN
- #1#2 #5
- }
- { \@@_parse_loop_break:wN }
+ \@@_parse_loop_main_sign:NNN
+ #1 #2 #4
}
- { \@@_parse_loop_break:wN }
+ { \@@_parse_loop_break:w }
}
}
}
@@ -1333,25 +1525,25 @@
% 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
+\cs_new_protected:Npn \@@_parse_loop_main_digit:NNNN #1#2#3#4
{
\bool_lazy_or:nnTF
- {#3} { ! \str_if_eq_p:nn {#5} { 0 } }
+ {#3} { ! \str_if_eq_p:nn {#4} { 0 } }
{
- \tl_put_right:Nn \l_@@_partial_tl {#5}
- \@@_parse_loop_main:NNNNN #1 #2 \c_true_bool #4
+ \tl_put_right:Nn \l_@@_partial_tl {#4}
+ \@@_parse_loop_main:NNNN #1 #2 \c_true_bool
}
- { \@@_parse_loop_main:NNNNN #1 #2 \c_false_bool #4 }
+ { \@@_parse_loop_main:NNNN #1 #2 \c_false_bool }
}
% \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
+\cs_new_protected:Npn \@@_parse_loop_main_decimal:N #1
{
\@@_parse_loop_main_store:NNN #1 \c_false_bool \c_false_bool
- \@@_parse_loop_after_decimal:NNN #1 #2
+ \@@_parse_loop_after_decimal:NN #1
}
% \end{macrocode}
% Starting an uncertainty part means storing the number to date as in other
@@ -1359,10 +1551,11 @@
% 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
+\cs_new_protected:Npn \@@_parse_loop_main_uncert:NN #1#2
{
\@@_parse_loop_main_store:NNN #1 #2 \c_false_bool
- \@@_parse_uncert:NN #1
+ \tl_clear:N \l_@@_uncert_tl
+ \@@_parse_uncert:N
}
% \end{macrocode}
% If a sign is found, terminate the current number, store the sign as the
@@ -1372,6 +1565,7 @@
\cs_new_protected:Npn \@@_parse_loop_main_sign:NNN #1#2#3
{
\@@_parse_loop_main_store:NNN #1 #2 \c_true_bool
+ \tl_put_right:NV \l_@@_uncert_tl \l_@@_flex_tl
\tl_set:Nn \l_@@_flex_tl { {#3} }
\@@_parse_loop_first:NNN
\l_@@_flex_tl \c_false_bool
@@ -1384,11 +1578,13 @@
% \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 }
+ {
+ \tl_if_empty:NTF \l_@@_partial_tl
+ { 0 }
+ { \exp_not:V \l_@@_partial_tl }
+ }
\bool_if:NT #2 { { } }
\bool_if:NT #3 { { } }
}
@@ -1400,23 +1596,23 @@
% 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
+\cs_new_protected:Npn \@@_parse_loop_after_decimal:NN #1#2
{
\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 }
+ \quark_if_recursion_tail_stop_do:Nn #2
+ { \@@_parse_loop_break:w \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
+ \tl_put_right:Nn \l_@@_partial_tl {#2}
+ \@@_parse_loop_main:NNNN
+ #1 \c_false_bool \c_true_bool
}
- { \@@_parse_loop_break:wN }
+ { \@@_parse_loop_break:w }
}
{
- \@@_parse_loop_main:NNNNN
- #1 \c_false_bool \c_true_bool #2 #3
+ \@@_parse_loop_main:NNNN
+ #1 \c_false_bool \c_true_bool #2
}
}
% \end{macrocode}
@@ -1424,7 +1620,7 @@
% 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
+\cs_new_protected:Npn \@@_parse_loop_break:w
#1 \q_recursion_stop
{
\tl_clear:N \l_@@_flex_tl
@@ -1442,7 +1638,6 @@
% \end{macro}
% \end{macro}
% \end{macro}
-% \end{macro}
%
% \begin{macro}{\@@_parse_sign:}
% \begin{macro}{\@@_parse_sign_aux:Nw}
@@ -1476,11 +1671,11 @@
% \end{macro}
% \end{macro}
%
-% \begin{macro}{\@@_parse_uncert:NN}
-% \begin{macro}{\@@_parse_uncert:NNNN}
-% \begin{macro}{\@@_parse_uncert_auxi:NN, \@@_parse_uncert_auxii:NN}
-% \begin{macro} {\@@_parse_uncert_auxii:N, \@@_parse_uncert_marker:N}
-% \begin{macro}{\@@_parse_uncert_extend:nnnN}
+% \begin{macro}{\@@_parse_uncert:N}
+% \begin{macro}{\@@_parse_uncert:NNN}
+% \begin{macro}{\@@_parse_uncert_auxi:N, \@@_parse_uncert_auxii:N}
+% \begin{macro} {\@@_parse_uncert_auxii:, \@@_parse_uncert_marker:}
+% \begin{macro}{\@@_parse_uncert_extend:nnn}
% \begin{macro}{\@@_parse_uncert_after:N}
% Parsing a combined uncertainty has a very restricted range of allowed
% tokens. A closing uncertainty token in the first place is an error,
@@ -1488,84 +1683,72 @@
% which require checking for significant digits. The non-digit function
% is separate to make the flow clearer.
% \begin{macrocode}
-\cs_new_protected:Npn \@@_parse_uncert:NN #1#2
+\cs_new_protected:Npn \@@_parse_uncert:N #1
{
- \quark_if_recursion_tail_stop_do:Nn #2
- { \@@_parse_loop_break:wN \q_recursion_stop }
- \tl_if_in:NnTF \l_@@_input_uncert_close_tl {#2}
- { \@@_parse_loop_break:wN }
+ \quark_if_recursion_tail_stop_do:Nn #1
+ { \@@_parse_loop_break:w \q_recursion_stop }
+ \tl_if_in:NnTF \l_@@_input_uncert_close_tl {#1}
+ { \@@_parse_loop_break:w }
{
- \@@_parse_uncert:NNNN
- #1 \c_false_bool \@@_parse_uncert_auxi:NN #2
+ \@@_parse_uncert:NNN
+ \c_false_bool \@@_parse_uncert_auxi:N #1
}
}
% \end{macrocode}
% Deal with digits: a simple question of whether they are significant.
% \begin{macrocode}
-\cs_new_protected:Npn \@@_parse_uncert:NNNN #1#2#3#4
+\cs_new_protected:Npn \@@_parse_uncert:NNN #1#2#3
{
- \quark_if_recursion_tail_stop_do:Nn #4
- { \@@_parse_loop_break:wN \q_recursion_stop }
- \tl_if_in:NnTF \l_@@_input_digit_tl {#4}
+ \quark_if_recursion_tail_stop_do:Nn #3
+ { \@@_parse_loop_break:w \q_recursion_stop }
+ \tl_if_in:NnTF \l_@@_input_digit_tl {#3}
{
\bool_lazy_or:nnTF
- {#2} { ! \str_if_eq_p:nn {#4} { 0 } }
+ {#1} { ! \str_if_eq_p:nn {#3} { 0 } }
{
- \tl_put_right:Nn \l_@@_partial_tl {#4}
- \@@_parse_uncert:NNNN #1 \c_true_bool #3
+ \tl_put_right:Nn \l_@@_partial_tl {#3}
+ \@@_parse_uncert:NNN \c_true_bool #2
}
- { \@@_parse_uncert:NNNN #1 \c_false_bool #3 }
+ { \@@_parse_uncert:NNN \c_false_bool #2 }
}
- { #3 #1#4 }
+ { #2 #3 }
}
% \end{macrocode}
% For the two auxiliaries, the difference is the handling of a
% decimal marker: one may be present, but only exactly one.
% \begin{macrocode}
-\cs_new_protected:Npn \@@_parse_uncert_auxi:NN #1#2
+\cs_new_protected:Npn \@@_parse_uncert_auxi:N #1
{
- \tl_if_in:NnTF \l_@@_input_uncert_close_tl {#2}
+ \tl_if_in:NnTF \l_@@_input_uncert_close_tl {#1}
{
- \@@_parse_uncert_auxiii:N #1
+ \@@_parse_uncert_auxiii:
\@@_parse_uncert_after:N
}
{
- \tl_if_in:NnTF \l_siunitx_number_input_decimal_tl {#2}
- { \@@_parse_uncert_marker:N #1 }
- { \@@_parse_loop_break:wN }
+ \tl_if_in:NnTF \l_siunitx_number_input_decimal_tl {#1}
+ { \@@_parse_uncert_marker: }
+ { \@@_parse_loop_break:w }
}
}
-\cs_new_protected:Npn \@@_parse_uncert_auxii:NN #1#2
+\cs_new_protected:Npn \@@_parse_uncert_auxii:N #1
{
- \tl_if_in:NnTF \l_@@_input_uncert_close_tl {#2}
+ \tl_if_in:NnTF \l_@@_input_uncert_close_tl {#1}
{
- \@@_parse_uncert_auxiii:N #1
+ \@@_parse_uncert_auxiii:
\@@_parse_uncert_after:N
}
- { \@@_parse_loop_break:wN }
+ { \@@_parse_loop_break:w }
}
% \end{macrocode}
% Deal with the closing bracket, which might leave us with nothing if there
% were no significant digits.
% \begin{macrocode}
-\cs_new_protected:Npn \@@_parse_uncert_auxiii:N #1
+\cs_new_protected:Npn \@@_parse_uncert_auxiii:
{
- \tl_if_empty:NTF \l_@@_partial_tl
- {
- \tl_put_right:Nx #1
- {
- {
- \bool_if:NT \l_@@_zero_uncert_bool
- { { S } { 0 } }
- }
- }
- }
- {
- \tl_set:Nx \l_@@_partial_tl
- { { S } { \exp_not:V \l_@@_partial_tl } }
- \@@_parse_loop_main_store:NNN #1
- \c_false_bool \c_false_bool
- }
+ \bool_lazy_and:nnT
+ { \l_@@_zero_uncert_bool }
+ { \tl_if_empty_p:N \l_@@_partial_tl }
+ { \tl_set:Nn \l_@@_partial_tl { 0 } }
}
% \end{macrocode}
% Handling a decimal marker in the uncertainty is a bit tricky: we need to make
@@ -1578,50 +1761,76 @@
% digits then a closing marker. So we can use that as a length: if it's
% too long we can stop.
% \begin{macrocode}
-\cs_new_protected:Npn \@@_parse_uncert_marker:N #1
- { \exp_after:wN \@@_parse_uncert_marker:nnnN #1 #1 }
-\cs_new_protected:Npn \@@_parse_uncert_marker:nnnN #1#2#3#4
+\cs_new_protected:Npn \@@_parse_uncert_marker:
+ {
+ \exp_after:wN \@@_parse_uncert_marker:nnn
+ \l_@@_parsed_tl
+ }
+\cs_new_protected:Npn \@@_parse_uncert_marker:nnn #1#2#3
{
\int_compare:nNnTF
{ \tl_count:N \l_@@_partial_tl } > { \tl_count:n {#2} }
- { \@@_parse_loop_break:wN }
- { \@@_parse_uncert_marker:nNw {#3} #4 }
+ { \@@_parse_loop_break:w }
+ { \@@_parse_uncert_marker:nw {#3} }
}
-\cs_new_protected:Npn \@@_parse_uncert_marker:nNw
- #1#2#3 \q_recursion_tail \q_recursion_stop
+\cs_new_protected:Npn \@@_parse_uncert_marker:nw
+ #1#2 \q_recursion_tail \q_recursion_stop
{
\int_compare:nNnTF
- { \tl_count:n {#3} - 1 } = { \tl_count:n {#1} }
+ { \tl_count:n {#2} - 1 } = { \tl_count:n {#1} }
{
\str_if_eq:eeTF
- { \exp_not:V \l_@@_partial_tl }
+ { \exp_not:V \l_@@_uncert_tl }
{ \prg_replicate:nn { \tl_count:N \l_@@_partial_tl } { 0 } }
- {
- \@@_parse_uncert:NNNN
- #2 \c_false_bool
- }
- {
- \@@_parse_uncert:NNNN
- #2 \c_true_bool
- }
- \@@_parse_uncert_auxii:NN
+ { \@@_parse_uncert:NNN \c_false_bool }
+ { \@@_parse_uncert:NNN \c_true_bool }
+ \@@_parse_uncert_auxii:N
}
- { \exp_after:wN \@@_parse_uncert_extend:nnnN #2 #2 }
- #3 \q_recursion_tail \q_recursion_stop
+ { \exp_after:wN \@@_parse_uncert_extend:nnn \l_@@_parsed_tl }
+ #2 \q_recursion_tail \q_recursion_stop
}
-\cs_new_protected:Npn \@@_parse_uncert_extend:nnnN #1#2#3#4
+\cs_new_protected:Npn \@@_parse_uncert_extend:nnn #1#2#3
{
- \tl_set:Nn #4 { {#1} {#2} { #3 0 } }
- \@@_parse_uncert:NNNN #4 \c_true_bool
- \@@_parse_uncert_auxii:NN
+ \tl_set:Nn \l_@@_parsed_tl { {#1} {#2} { #3 0 } }
+ \@@_parse_uncert:NNN \c_true_bool
+ \@@_parse_uncert_auxii:N
}
% \end{macrocode}
-% No further tokens are allowed after an uncertainty in parenthesis.
+% At the end of collection, we can either start another one or be done:
+% either way we move the data around.
% \begin{macrocode}
\cs_new_protected:Npn \@@_parse_uncert_after:N #1
{
- \quark_if_recursion_tail_stop:N #1
- \@@_parse_loop_break:wN
+ \tl_set:Nx \l_@@_uncert_tl
+ {
+ \exp_not:V \l_@@_uncert_tl
+ \tl_if_empty:NF \l_@@_partial_tl
+ { { \exp_not:V \l_@@_partial_tl } }
+ }
+ \tl_clear:N \l_@@_partial_tl
+ \quark_if_recursion_tail_stop_do:Nn #1
+ {
+ \tl_set:Nx \l_@@_parsed_tl
+ {
+ \exp_not:V \l_@@_parsed_tl
+ {
+ \tl_if_empty:NF \l_@@_uncert_tl
+ {
+ {
+ \prg_replicate:nn
+ { \tl_count:N \l_@@_uncert_tl }
+ { S }
+ }
+ \exp_not:V \l_@@_uncert_tl
+ }
+ }
+ }
+ \tl_clear:N \l_@@_partial_tl
+ \tl_clear:N \l_@@_uncert_tl
+ }
+ \tl_if_in:NnTF \l_@@_input_uncert_open_tl {#1}
+ { \@@_parse_uncert:N }
+ { \@@_parse_loop_break:w }
}
% \end{macrocode}
% \end{macro}
@@ -1645,7 +1854,8 @@
% \l_@@_round_half_even_bool ,
% \l_@@_round_mode_tl ,
% \l_@@_round_pad_bool ,
-% \l_@@_round_precision_int
+% \l_@@_round_precision_int ,
+% \l_@@_round_positive_bool
% }
% \begin{macrocode}
\keys_define:nn { siunitx }
@@ -1679,6 +1889,8 @@
\l_@@_round_pad_bool ,
round-precision .int_set:N =
\l_@@_round_precision_int ,
+ round-zero-positive .bool_set:N =
+ \l_@@_round_positive_bool
}
\bool_new:N \l_@@_round_half_even_bool
\tl_new:N \l_@@_exponent_mode_tl
@@ -2113,8 +2325,12 @@
% \begin{macro}{\@@_digits:NN}
% \begin{macro}[EXP]{\@@_digits:nnnnnnn}
% \begin{macro}[EXP]{\@@_digits:nn}
-% \begin{macro}[EXP]{\@@_digits_uncert:nnn}
-% \begin{macro}[EXP]{\@@_digits_uncert_S:nn}
+% \begin{macro}[EXP]{\@@_digits_uncert:nnw}
+% \begin{macro}[EXP]
+% {\@@_digits_uncert_A:nn, \@@_digits_uncert_S:nn, \@@_digits_uncert_aux:nn}
+% \begin{macro}[EXP]{\@@_digits_uncert_A:nnn}
+% \begin{macro}[EXP]{\@@_digits_uncert:nN}
+% \begin{macro}[EXP]{\@@_digits_uncert:nNw}
% Forcing a minimum number of digits in each part is quite easy. As
% the common case is that we don't do anything here, there is no real need
% to optimise the calculation (normally also numbers have only a few digits).
@@ -2135,7 +2351,10 @@
\exp_not:n {#4}
\@@_digits:nn \l_@@_min_decimal_int {#4}
}
- { \tl_if_blank:nF {#5} { \@@_digits_uncert:nnn {#4} #5 } }
+ {
+ \tl_if_blank:nF {#5}
+ { \@@_digits_uncert:nnw {#4} #5 \q_stop }
+ }
\exp_not:n { {#6} {#7} }
}
\cs_new:Npn \@@_digits:nn #1#2
@@ -2144,12 +2363,26 @@
{ #1 - \tl_count:n {#2} } > 0
{ \prg_replicate:nn { #1 - \tl_count:n {#2} } { 0 } }
}
-\cs_new:Npn \@@_digits_uncert:nnn #1#2#3
+\cs_new:Npn \@@_digits_uncert:nnw #1#2#3 \q_stop
{
{ #2 }
- { \use:c { @@_digits_uncert_ #2 :nn } {#1} {#3} }
+ \cs_if_exist:cTF { @@_digits_uncert_ #2 :nn }
+ { { \use:c { @@_digits_uncert_ #2 :nn } {#1} {#3} } }
+ {
+ \@@_digits_uncert:nN {#1} #2 \q_recursion_tail
+ #3 \q_recursion_stop
+ }
+ }
+\cs_new:Npn \@@_digits_uncert_A:nn #1#2
+ { \@@_digits_uncert_A:nnn {#1} #2 }
+\cs_new:Npn \@@_digits_uncert_A:nnn #1#2#3
+ {
+ { \@@_digits_uncert_aux:nn {#1} {#2} }
+ { \@@_digits_uncert_aux:nn {#1} {#3} }
}
\cs_new:Npn \@@_digits_uncert_S:nn #1#2
+ { \@@_digits_uncert_aux:nn {#1} {#2} }
+\cs_new:Npn \@@_digits_uncert_aux:nn #1#2
{
\exp_not:n {#2}
\@@_digits:nn
@@ -2160,12 +2393,25 @@
}
{#2}
}
+\cs_new:Npn \@@_digits_uncert:nN #1#2
+ {
+ \quark_if_recursion_tail_stop:N #2
+ \@@_digits_uncert:nNw {#1} #2
+ }
+\cs_new:Npn \@@_digits_uncert:nNw #1#2#3 \q_recursion_tail #4
+ {
+ { \use:c { @@_digits_uncert_ #2 :nn } {#1} {#4} }
+ \@@_digits_uncert:nN {#1} #3 \q_recursion_tail
+ }
% \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
%
% \begin{macro}{\@@_drop_exponent:NN}
% \begin{macro}[EXP]{\@@_drop_exponent:nnnnnnn}
@@ -2255,7 +2501,7 @@
% \@@_round_engineering:nn ,
% \@@_round_fixed:nn ,
% \@@_round_input:nn ,
-% \@@_round_scientifitc:nn
+% \@@_round_scientific:nn
% }
% \begin{macro}[EXP]{\@@_round_engineering:NNNNn}
% \begin{macro}[EXP]{\@@_round_engineering:nnN}
@@ -2763,17 +3009,19 @@
{ \@@_round_places_finalise:nnnnnnn #1 }
\cs_new:Npn \@@_round_places_finalise:nnnnnnn #1#2#3#4#5#6#7
{
- \bool_lazy_and:nnTF
- { \str_if_eq_p:nn {#3} { 0 } }
- {
- \str_if_eq_p:ee
- { \exp_not:n {#4} } { \prg_replicate:nn { \tl_count:n {#4} } { 0 } }
- }
+ \str_if_eq:eeTF
+ { \exp_not:n {#3#4} }
+ { \prg_replicate:nn { \tl_count:n {#3#4} } { 0 } }
{
\tl_if_empty:NTF \l_@@_round_min_tl
{
\exp_not:n { {#1} }
- { \str_if_eq:nnF {#2} { - } { \exp_not:n {#2} } }
+ {
+ \bool_lazy_and:nnF
+ { \l_@@_round_positive_bool }
+ { \str_if_eq_p:nn {#2} { - } }
+ { \exp_not:n {#2} }
+ }
\exp_not:n { {#3} {#4} {#5} {#6} {#7} }
}
{
@@ -3107,23 +3355,28 @@
%
% \begin{variable}
% {
-% \l_@@_bracket_negative_bool ,
-% \l_@@_implicit_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_@@_output_exp_marker_tl ,
-% \l_@@_output_uncert_close_tl ,
-% \l_@@_output_uncert_open_tl ,
-% \l_@@_uncert_mode_tl ,
-% \l_@@_uncert_separator_tl ,
-% \l_@@_tight_bool ,
-% \l_@@_unity_mantissa_bool ,
-% \l_@@_zero_exponent_bool ,
+% \l_@@_bracket_negative_bool ,
+% \l_@@_implicit_plus_bool ,
+% \l_@@_exponent_base_tl ,
+% \l_@@_exponent_product_tl ,
+% \l_@@_group_size_int ,
+% \l_@@_group_first_int ,
+% \l_@@_group_decimal_bool ,
+% \l_@@_group_integer_bool ,
+% \l_@@_group_minimum_int ,
+% \l_@@_group_separator_tl ,
+% \l_@@_negative_color_tl ,
+% \l_@@_output_exp_marker_tl ,
+% \l_@@_output_uncert_close_tl ,
+% \l_@@_output_uncert_open_tl ,
+% \l_@@_uncert_desc_mode_tl ,
+% \l_@@_uncert_desc_separator_tl ,
+% \l_@@_uncert_desc_clist ,
+% \l_@@_uncert_mode_tl ,
+% \l_@@_uncert_separator_tl ,
+% \l_@@_tight_bool ,
+% \l_@@_unity_mantissa_bool ,
+% \l_@@_zero_exponent_bool ,
% \l_@@_zero_integer_bool
% }
% Keys producing tokens in the output.
@@ -3138,6 +3391,15 @@
\l_@@_exponent_base_tl ,
exponent-product .tl_set:N =
\l_@@_exponent_product_tl ,
+ digit-group-size .meta:n =
+ {
+ digit-group-first-size = {#1} ,
+ digit-group-other-size = {#1}
+ } ,
+ digit-group-first-size .int_set:N =
+ \l_@@_group_first_int ,
+ digit-group-other-size .int_set:N =
+ \l_@@_group_size_int ,
group-digits .choice: ,
group-digits / all .code:n =
{
@@ -3184,14 +3446,25 @@
\l_@@_zero_integer_bool ,
tight-spacing .bool_set:N =
\l_@@_tight_bool ,
+ uncertainty-descriptor-mode .choices:nn =
+ { bracket , bracket-separator , separator , subscript }
+ { \tl_set_eq:NN \l_@@_uncert_desc_mode_tl \l_keys_choice_tl } ,
+ uncertainty-descriptor-separator .tl_set:N =
+ \l_@@_uncert_desc_separator_tl ,
+ uncertainty-descriptors .clist_set:N =
+ \l_@@_uncert_desc_clist ,
uncertainty-mode .choices:nn =
{ compact , compact-marker , full , separate }
{ \tl_set_eq:NN \l_@@_uncert_mode_tl \l_keys_choice_tl } ,
uncertainty-separator .tl_set:N =
- \l_@@_uncert_separator_tl
+ \l_@@_uncert_separator_tl ,
+ zero-decimal-as-symbol .bool_set:N =
+ \l_@@_zero_symbol_bool ,
+ zero-symbol .tl_set:N = \l_@@_zero_symbol_tl
}
\bool_new:N \l_@@_group_decimal_bool
\bool_new:N \l_@@_group_integer_bool
+\tl_new:N \l_@@_uncert_desc_mode_tl
\tl_new:N \l_@@_uncert_mode_tl
% \end{macrocode}
% \end{variable}
@@ -3213,25 +3486,49 @@
% \begin{macro}[rEXP]{\@@_output_integer:nnn}
% \begin{macro}[rEXP]{\@@_output_decimal:nn, \@@_output_decimal:fn}
% \begin{macro}[rEXP]{\@@_output_digits:nn}
-% \begin{macro}[rEXP]{\@@_output_integer_aux:n}
+% \begin{macro}[rEXP]{\@@_output_digit_separator:N}
+% \begin{macro}[rEXP]{\@@_output_integer_3_3:n}
% \begin{macro}[rEXP]
% {
% \@@_output_integer_aux_0:n,
% \@@_output_integer_aux_1:n,
% \@@_output_integer_aux_2:n
% }
-% \begin{macro}[rEXP]{\@@_output_decimal_aux:n}
-% \begin{macro}[rEXP]{\@@_output_decimal_loop:NNNN}
% \begin{macro}[rEXP]{\@@_output_integer_first:nnNN}
% \begin{macro}[rEXP]{\@@_output_integer_loop:NNNN}
+% \begin{macro}[rEXP]{\@@_output_integer_first:n}
+% \begin{macro}[rEXP]{\@@_output_integer_aux:n}
+% \begin{macro}[rEXP]{\@@_output_integer_loop:NnnN}
+% \begin{macro}[rEXP]{\@@_output_decimal_3_3:n}
+% \begin{macro}[rEXP]{\@@_output_decimal_loop:NNNN}
+% \begin{macro}[rEXP]{\@@_output_decimal_3_2:n}
+% \begin{macro}[rEXP]{\@@_output_decimal:NNNw}
+% \begin{macro}[rEXP]{\@@_output_decimal_loop:NN}
+% \begin{macro}[rEXP]{\@@_output_decimal_first:n}
+% \begin{macro}[rEXP]{\@@_output_decimal_loop:NnnN}
% \begin{macro}[rEXP]{\@@_output_uncertainty:nnn}
% \begin{macro}[rEXP]{\@@_output_uncertainty_unaligned:n}
-% \begin{macro}[rEXP]{\@@_output_uncert_S:nnnw}
+% \begin{macro}[rEXP]{\@@_output_uncert:nnnn}
+% \begin{macro}[rEXP]{\@@_output_uncert:nnnnn}
+% \begin{macro}[rEXP]{\@@_output_uncert_loop:nnN}
+% \begin{macro}[rEXP]{\@@_output_uncert_loop:nnNw}
% \begin{macro}[rEXP]
-% {\@@_output_uncert_S_aux:nnn, \@@_output_uncert_S_aux:fnn}
+% {
+% \@@_output_uncert_desc_bracket:n ,
+% \@@_output_uncert_desc_bracket-separator:n ,
+% \@@_output_uncert_desc_separator:n ,
+% \@@_output_uncert_desc_subscript:n
+% }
+% \begin{macro}[rEXP]{\@@_output_uncert_A_loop:nnn, \@@_output_uncert_S_loop:nnn}
+% \begin{macro}[rEXP]{\@@_output_uncert_S_loop:w}
+% \begin{macro}[rEXP]{\@@_output_uncert_A:nnnn, \@@_output_uncert_A_multi:nnnn}
+% \begin{macro}[rEXP]{\@@_output_uncert_A:nnnnn}
% \begin{macro}[rEXP]
-% {\@@_output_uncert_S:nnnw, \@@_output_uncert_S:fnw}
-% \begin{macro}[rEXP]{\@@_output_uncert_S:nnw}
+% {
+% \@@_output_uncert_S:nnnn ,
+% \@@_output_uncert_S_sep:nnnn ,
+% \@@_output_uncert_S_multi:nnnn
+% }
% \begin{macro}[rEXP]
% {
% \@@_output_uncert_S_compact:nn ,
@@ -3239,6 +3536,13 @@
% \@@_output_uncert_S_full:nn
% }
% \begin{macro}[rEXP]
+% {\@@_output_uncert_augment:nnnn}
+% \begin{macro}[rEXP]
+% {\@@_output_uncert_augment:nnn}
+% \begin{macro}[rEXP]
+% {\@@_output_uncert_augment:nnnw, \@@_output_uncert_augment:fnnw}
+% \begin{macro}[rEXP]{\@@_output_uncert_augment:nnw}
+% \begin{macro}[rEXP]
% {
% \@@_output_exponent:nnnnn ,
% \@@_output_exponent_auxi:nnnnn ,
@@ -3420,7 +3724,17 @@
}
\exp_not:n {#2}
\str_if_eq:nnF {#1} { \empty }
- { \@@_output_digits:nn { decimal } {#1} }
+ {
+ \bool_lazy_and:nnTF
+ { \l_@@_zero_symbol_bool }
+ {
+ \str_if_eq_p:ee
+ {#1}
+ { \prg_replicate:nn { \tl_count:n {#1} } { 0 } }
+ }
+ { \exp_not:V \l_@@_zero_symbol_tl }
+ { \@@_output_digits:nn { decimal } {#1} }
+ }
}
\cs_generate_variant:Nn \@@_output_decimal:nn { f }
\cs_new:Npn \@@_output_digits:nn #1#2
@@ -3430,16 +3744,37 @@
\int_compare:nNnTF
{ \tl_count:n {#2} } < \l_@@_group_minimum_int
{ \exp_not:n {#2} }
- { \use:c { @@_output_ #1 _aux:n } {#2} }
+ {
+ \cs_if_exist_use:cF
+ {
+ @@_output_ #1 _
+ \int_use:N \l_@@_group_first_int
+ _
+ \int_use:N \l_@@_group_size_int
+ :n
+ }
+ { \use:c { @@_output_ #1 _first: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.
+% An auxiliary to ensure spacing is correct.
% \begin{macrocode}
-\cs_new:Npn \@@_output_integer_aux:n #1
+\cs_new:Npn \@@_output_digit_separator:N #1
+ {
+ \str_if_eq:VnTF #1 { , }
+ { \exp_not:N \mathord }
+ { \use:n }
+ { \exp_not:V #1 }
+ }
+% \end{macrocode}
+% For standard grouping of 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:cpn { @@_output_integer_3_3:n } #1
{
\use:c
{
@@ -3462,21 +3797,51 @@
}
\cs_new:Npn \@@_output_integer_loop:NNNN #1#2#3#4
{
- \str_if_eq:VnTF \l_@@_group_separator_tl { , }
- { \exp_not:N \mathord }
- { \use:n }
- { \exp_not:V \l_@@_group_separator_tl }
+ \@@_output_digit_separator:N \l_@@_group_separator_tl
\exp_not:n {#1#2#3}
\quark_if_nil:NF #4
{ \@@_output_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.
+% There is no clever way of doing an uneven integer grouping, so just provide
+% a slow generic approach. This is more-or-less the same as the generic
+% decimal code, but with the output reversed. The only wrinkle is we need to
+% reverse the entire input again, so it has to be carried as an argument.
% \begin{macrocode}
-\cs_new:Npn \@@_output_decimal_aux:n #1
+\cs_new:Npn \@@_output_integer_first:n #1
+ {
+ \exp_args:Ne \@@_output_integer_aux:n { \tl_reverse:n {#1} }
+ }
+\cs_new:Npn \@@_output_integer_aux:n #1
+ {
+ \@@_output_integer_loop:NnnN \l_@@_group_first_int { 0 } { }
+ #1 \q_recursion_tail \q_recursion_stop
+ }
+\cs_new:Npn \@@_output_integer_loop:NnnN #1#2#3#4
+ {
+ \quark_if_recursion_tail_stop_do:Nn #4 {#3}
+ \int_compare:nNnTF { #2 + 1 } > #1
+ {
+ \@@_output_integer_loop:NnnN
+ \l_@@_group_size_int { 1 }
+ {
+ \exp_not:n {#4}
+ \@@_output_digit_separator:N \l_@@_group_separator_tl
+ #3
+ }
+ }
+ {
+ \@@_output_integer_loop:NnnN #1 { #2 + 1 }
+ { \exp_not:n {#4} #3 }
+ }
+ }
+% \end{macrocode}
+% For standard decimal grouping, 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:cpn { @@_output_decimal_3_3:n } #1
{
\@@_output_decimal_loop:NNNN \c_empty_tl
#1 \q_nil \q_nil \q_nil
@@ -3485,7 +3850,7 @@
{
\quark_if_nil:NF #2
{
- \exp_not:V #1
+ \@@_output_digit_separator:N #1
\exp_not:n {#2}
\quark_if_nil:NTF #3
{ \use_none:n }
@@ -3502,38 +3867,185 @@
}
}
% \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.
+% The same trick for the group-of-two case, but as the first pass is already
+% done, there is not need to worry about the separator.
+% \begin{macrocode}
+\cs_new:cpn { @@_output_decimal_3_2:n } #1
+ {
+ \int_compare:nNnTF { \tl_count:n {#1} } > 2
+ { \@@_output_decimal:NNNw #1 \q_stop }
+ { \exp_not:n {#1} }
+ }
+\cs_new:Npn \@@_output_decimal:NNNw #1#2#3#4 \q_stop
+ {
+ \exp_not:n {#1#2#3}
+ \@@_output_decimal_loop:NN #4 \q_nil \q_nil
+ }
+\cs_new:Npn \@@_output_decimal_loop:NN #1#2
+ {
+ \quark_if_nil:NF #1
+ {
+ \@@_output_digit_separator:N
+ \l_@@_group_separator_tl
+ \exp_not:n {#1}
+ \quark_if_nil:NTF #2
+ { \use_none:n }
+ {
+ \exp_not:n {#2}
+ \@@_output_decimal_loop:NN
+ }
+ }
+ }
+% \end{macrocode}
+% The generic decimal separator: simply count the digits.
+% \begin{macrocode}
+\cs_new:Npn \@@_output_decimal_first:n #1
+ {
+ \@@_output_decimal_loop:NnnN \l_@@_group_first_int { 0 } { }
+ #1 \q_recursion_tail \q_recursion_stop
+ }
+\cs_new:Npn \@@_output_decimal_loop:NnnN #1#2#3#4
+ {
+ \quark_if_recursion_tail_stop_do:Nn #4 { \exp_not:n {#3} }
+ \int_compare:nNnTF { #2 + 1 } > #1
+ {
+ \exp_not:n {#3}
+ \@@_output_digit_separator:N
+ \l_@@_group_separator_tl
+ \@@_output_decimal_loop:NnnN \l_@@_group_size_int { 1 } {#4}
+ }
+ { \@@_output_decimal_loop:NnnN #1 { #2 + 1 } { #3 #4 } }
+ }
+% \end{macrocode}
+% The lead-off here is to deal with the common cases: no uncertainty at all
+% or a single uncertainty. Otherwise we have to move to a mapping.
% \begin{macrocode}
\cs_new:Npn \@@_output_uncertainty:nnn #1#2#3
{
\tl_if_blank:nTF {#1}
{ \@@_output_uncertainty_unaligned:n {#3} }
{
- \use:c { @@_output_uncert_ \tl_head:n {#1} :nnnw }
- {#2} {#3} #1
+ \cs_if_exist:cTF
+ { @@_output_uncert_ \tl_head:n {#1} :nnnn }
+ {
+ \use:c { @@_output_uncert_ \tl_head:n {#1} :nnnn }
+ {#2} {#3} #1
+ }
+ { \@@_output_uncert:nnnn {#2} {#3} #1 }
}
}
\cs_new:Npn \@@_output_uncertainty_unaligned:n #1
{ \exp_not:n { #1 #1 #1 #1 } }
-\cs_new:Npn \@@_output_uncert_S:nnnw #1#2#3#4
+% \end{macrocode}
+% For handling a list of uncertainties, we also need the descriptors. There
+% is no way to reasonably deal with alignment of an open-ended list, so
+% the treatment is as-for no uncertainty at all.
+% \begin{macrocode}
+\cs_new:Npn \@@_output_uncert:nnnn #1#2#3#4
{
- \str_if_eq:VnTF \l_@@_uncert_mode_tl { separate }
+ \exp_args:NV \@@_output_uncert:nnnnn \l_@@_uncert_desc_clist
+ {#1} {#2} {#3} {#4}
+ }
+\cs_new:Npn \@@_output_uncert:nnnnn #1#2#3#4#5
+ {
+ \@@_output_uncert_loop:nnN {#2} {#3}
+ #4 \q_recursion_tail #1 , \q_recursion_stop {#5}
+ }
+\cs_new:Npn \@@_output_uncert_loop:nnN #1#2#3
+ {
+ \quark_if_recursion_tail_stop:N #3
+ \@@_output_uncert_loop:nnNw {#1} {#2} #3
+ }
+\cs_new:Npn \@@_output_uncert_loop:nnNw
+ #1#2#3#4 \q_recursion_tail #5 , #6 \q_recursion_stop #7
+ {
+ \use:c { @@_output_uncert_ #3 _loop:nnn } {#1} {#2} {#7}
+ \tl_if_blank:nF {#5}
+ { \use:c { @@_output_uncert_desc_ \l_@@_uncert_desc_mode_tl :n } {#5} }
+ \@@_output_uncert_loop:nnN {#1} {#2} #4
+ \q_recursion_tail #6 , \q_recursion_stop
+ }
+\cs_new:Npn \@@_output_uncert_desc_bracket:n #1
+ {
+ \exp_not:V \l_@@_bracket_open_tl
+ \exp_not:V \l_siunitx_unit_font_tl
+ { \exp_not:n {#1} }
+ \exp_not:V \l_@@_bracket_close_tl
+ }
+\cs_new:cpn { @@_output_uncert_desc_bracket-separator:n } #1
+ {
+ \exp_not:V \l_@@_uncert_desc_separator_tl
+ \exp_not:V \l_@@_bracket_open_tl
+ \exp_not:V \l_siunitx_unit_font_tl
+ { \exp_not:n {#1} }
+ \exp_not:V \l_@@_bracket_close_tl
+ }
+\cs_new:Npn \@@_output_uncert_desc_separator:n #1
+ {
+ \exp_not:V \l_@@_uncert_desc_separator_tl
+ \exp_not:V \l_siunitx_unit_font_tl
+ { \exp_not:n {#1} }
+ }
+\cs_new:Npx \@@_output_uncert_desc_subscript:n #1
+ {
+ \char_generate:nn { `\_ } { 8 }
{
- \exp_not:n {#2}
- \bool_if:NTF \l_@@_tight_bool
- { \mathord }
- { \use:n }
- { \exp_not:n { \pm } }
- \exp_not:n {#2}
- \@@_output_uncert_S_aux:nnn
- { \int_eval:n { \tl_count:n {#4} - \tl_count:n {#1} } }
- {#4} {#2}
+ \exp_not:N \exp_not:V \exp_not:N \l_siunitx_unit_font_tl
+ { \exp_not:N \exp_not:n {#1} }
}
+ }
+% \end{macrocode}
+% Here, we have to tidy up so the alignment point only applies to the first
+% |S|-type uncertainty.
+% \begin{macrocode}
+\cs_new:Npn \@@_output_uncert_A_loop:nnn #1#2#3
+ { \@@_output_uncert_A_multi:nnnn {#1} {#2} { A } {#3} }
+\cs_new:Npn \@@_output_uncert_S_loop:nnn #1#2#3
+ {
+ \@@_output_uncert_S_multi:nnnn {#1} {#2} { S } {#3}
+ \@@_output_uncert_S_loop:w
+ }
+\cs_new:Npn \@@_output_uncert_S_loop:w #1 \@@_output_uncert_loop:nnN #2#3
+ {
+ #1
+ \@@_output_uncert_loop:nnN {#2} { }
+ }
+% \end{macrocode}
+% Printing an asymmetrical uncertainty is more straight-forward as they are
+% always given in a single format. The only issue is handling the catcode.
+% \begin{macrocode}
+\cs_new:Npn \@@_output_uncert_A:nnnn #1#2#3#4
+ { \@@_output_uncert_A:nnnnn {#1} {#2} {#3} #4 }
+\cs_new_eq:NN \@@_output_uncert_A_multi:nnnn
+ \@@_output_uncert_A:nnnn
+\cs_new:Npx \@@_output_uncert_A:nnnnn #1#2#3#4#5
+ {
+ ^
+ {
+ +
+ \exp_not:N \@@_output_uncert_augment:nnnn
+ {#4} {#1} {#4} {#2}
+ }
+ \char_generate:nn { `\_ } { 8 }
+ {
+ -
+ \exp_not:N \@@_output_uncert_augment:nnnn
+ {#5} {#1} {#5} {#2}
+ }
+ \exp_not:N \@@_output_uncertainty_unaligned:n {#2}
+ }
+% \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 \@@_output_uncert_S:nnnn #1#2#3#4
+ {
+ \str_if_eq:VnTF \l_@@_uncert_mode_tl { separate }
+ { \@@_output_uncert_S_sep:nnnn {#1} {#2} {#3} {#4} }
{
\exp_not:V \l_@@_uncert_separator_tl
\exp_not:V \l_@@_output_uncert_open_tl
@@ -3542,11 +4054,51 @@
\@@_output_uncertainty_unaligned:n {#2}
}
}
-\cs_new:Npn \@@_output_uncert_S_aux:nnn #1#2#3
+\cs_new:Npn \@@_output_uncert_S_sep:nnnn #1#2#3#4
+ {
+ \exp_not:n {#2}
+ \bool_if:NTF \l_@@_tight_bool
+ { \mathord }
+ { \use:n }
+ { \exp_not:n { \pm } }
+ \exp_not:n {#2}
+ \@@_output_uncert_augment:nnnn {#4} {#1} {#4} {#2}
+ }
+\cs_new_eq:NN \@@_output_uncert_S_multi:nnnn
+ \@@_output_uncert_S_sep:nnnn
+% \end{macrocode}
+% Handle the content of brackets: the only complex case is the
+% mixed situation.
+% \begin{macrocode}
+\cs_new:Npn \@@_output_uncert_S_compact:nn #1#2
+ { \exp_not:n {#2} }
+\cs_new:cpn { @@_output_uncert_S_compact-marker:nn } #1#2
+ {
+ \bool_lazy_or:nnTF
+ { \tl_if_blank_p:n {#1} }
+ { ! \int_compare_p:nNn { \tl_count:n {#2} } > { \tl_count:n {#1} } }
+ { \@@_output_uncert_S_compact:nn }
+ { \@@_output_uncert_S_full:nn }
+ {#1} {#2}
+ }
+\cs_new:Npn \@@_output_uncert_S_full:nn #1#2
+ {
+ \@@_output_uncert_augment:nnnn {#2} {#1} {#2} { }
+ }
+% \end{macrocode}
+% Convert the internal (short) form of an uncertainty to the longer form.
+% \begin{macrocode}
+\cs_new:Npn \@@_output_uncert_augment:nnnn #1#2#3#4
+ {
+ \exp_args:Nf \@@_output_uncert_augment:nnn
+ { \int_eval:n { \tl_count:n {#1} - \tl_count:n {#2} } }
+ {#3} {#4}
+ }
+\cs_new:Npn \@@_output_uncert_augment:nnn #1#2#3
{
\int_compare:nNnTF {#1} > 0
{
- \@@_output_uncert_S_aux:fnnw
+ \@@_output_uncert_augment:fnnw
{ \int_eval:n { #1 - 1 } }
{#3}
{ }
@@ -3562,49 +4114,27 @@
{#3}
}
}
-\cs_generate_variant:Nn \@@_output_uncert_S_aux:nnn { f }
-\cs_new:Npn \@@_output_uncert_S_aux:nnnw #1#2#3#4
+\cs_new:Npn \@@_output_uncert_augment:nnnw #1#2#3#4
{
\quark_if_nil:NF #4
{
\int_compare:nNnTF {#1} = 0
- { \@@_output_uncert_S_aux:nnw {#3#4} {#2} }
+ { \@@_output_uncert_augment:nnw {#3#4} {#2} }
{
- \@@_output_uncert_S_aux:fnnw
+ \@@_output_uncert_augment:fnnw
{ \int_eval:n { #1 - 1 } }
{#2}
{#3#4}
}
}
}
-\cs_generate_variant:Nn \@@_output_uncert_S_aux:nnnw { f }
-\cs_new:Npn \@@_output_uncert_S_aux:nnw #1#2#3 \q_nil
+\cs_generate_variant:Nn \@@_output_uncert_augment:nnnw { f }
+\cs_new:Npn \@@_output_uncert_augment:nnw #1#2#3 \q_nil
{
\@@_output_digits:nn { integer } {#1}
\@@_output_decimal:nn {#3} {#2}
}
% \end{macrocode}
-% Handle the content of brackets: the only complex case is the
-% mixed situation.
-% \begin{macrocode}
-\cs_new:Npn \@@_output_uncert_S_compact:nn #1#2
- { \exp_not:n {#2} }
-\cs_new:cpn { @@_output_uncert_S_compact-marker:nn } #1#2
- {
- \bool_lazy_or:nnTF
- { \tl_if_blank_p:n {#1} }
- { ! \int_compare_p:nNn { \tl_count:n {#2} } > { \tl_count:n {#1} } }
- { \@@_output_uncert_S_compact:nn }
- { \@@_output_uncert_S_full:nn }
- {#1} {#2}
- }
-\cs_new:Npn \@@_output_uncert_S_full:nn #1#2
- {
- \@@_output_uncert_S_aux:fnn
- { \int_eval:n { \tl_count:n {#2} - \tl_count:n {#1} } }
- {#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
@@ -3707,6 +4237,24 @@
% \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}
%
@@ -3820,51 +4368,61 @@
% \begin{macrocode}
\keys_set:nn { siunitx }
{
- bracket-ambiguous-numbers = true ,
- bracket-negative-numbers = false ,
- drop-exponent = false ,
- drop-uncertainty = false ,
- drop-zero-decimal = false ,
- evaluate-expression = false ,
- exponent-base = 10 ,
- exponent-mode = input ,
- exponent-product = \times ,
- expression = #1 ,
- fixed-exponent = 0 ,
- group-digits = all ,
- group-minimum-digits = 5 ,
- group-separator = \, , % (
- input-close-uncertainty = ) ,
- 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 ,
- minimum-decimal-digits = 0 ,
- minimum-integer-digits = 0 ,
- negative-color = , % (
- output-close-uncertainty = ) ,
- output-decimal-marker = . ,
- output-open-uncertainty = ( , % )
- parse-numbers = true ,
- print-implicit-plus = false ,
- print-unity-mantissa = true ,
- print-zero-exponent = false ,
- print-zero-integer = true ,
- retain-explicit-decimal-marker = false ,
- retain-explicit-plus = false ,
- retain-zero-uncertainty = false ,
- round-half = up ,
- round-minimum = 0 ,
- round-mode = none ,
- round-pad = true ,
- round-precision = 2 ,
- tight-spacing = false ,
- uncertainty-mode = compact ,
- uncertainty-separator =
+ bracket-ambiguous-numbers = true ,
+ bracket-negative-numbers = false ,
+ drop-exponent = false ,
+ drop-uncertainty = false ,
+ drop-zero-decimal = false ,
+ evaluate-expression = false ,
+ exponent-base = 10 ,
+ exponent-mode = input ,
+ exponent-product = \times ,
+ expression = #1 ,
+ fixed-exponent = 0 ,
+ digit-group-size = 3 ,
+ digit-group-first-size = 3 ,
+ digit-group-other-size = 3 ,
+ group-digits = all ,
+ group-minimum-digits = 5 ,
+ group-separator = \, , % (
+ input-close-uncertainty = ) ,
+ 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 ,
+ minimum-decimal-digits = 0 ,
+ minimum-integer-digits = 0 ,
+ negative-color = , % (
+ output-close-uncertainty = ) ,
+ output-decimal-marker = . ,
+ output-open-uncertainty = ( , % )
+ parse-numbers = true ,
+ print-implicit-plus = false ,
+ print-unity-mantissa = true ,
+ print-zero-exponent = false ,
+ print-zero-integer = true ,
+ retain-explicit-decimal-marker = false ,
+ retain-explicit-plus = false ,
+ retain-negative-zero = false ,
+ retain-zero-uncertainty = false ,
+ round-half = up ,
+ round-minimum = 0 ,
+ round-mode = none ,
+ round-pad = true ,
+ round-precision = 2 ,
+ round-zero-positive = true ,
+ tight-spacing = false ,
+ uncertainty-descriptor-mode = bracket-separator ,
+ uncertainty-descriptor-separator = \ ,
+ uncertainty-descriptors = ,
+ uncertainty-mode = compact ,
+ uncertainty-separator = ,
+ zero-decimal-as-symbol = false ,
+ zero-symbol = \mbox { --- }
}
% \end{macrocode}
%