Skip to content

Commit

Permalink
Add core support for asymmetrical uncertainties (see #675)
Browse files Browse the repository at this point in the history
  • Loading branch information
josephwright committed Jul 26, 2023
1 parent 5dacb0d commit c6a8b7a
Show file tree
Hide file tree
Showing 5 changed files with 217 additions and 90 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Expand Up @@ -19,6 +19,9 @@ Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to
- Option `uncertainty-round-direction` (see issue
[\#628](https://github.com/josephwright/siunitx/issues/628))
- Option `input-symmetrical-uncertainty-signs`
- Support for asymmetrical uncertainties, including new option
`input-uncertainty-divider` (see issue
[\#675](https://github.com/josephwright/siunitx/issues/675))

### Changed
- Support bracing of decimal marker in tables as an alternative
Expand Down
82 changes: 68 additions & 14 deletions siunitx-number.dtx
Expand Up @@ -411,6 +411,12 @@
% \end{syntax}
% \end{function}
%
% \begin{function}{input-uncertainty-divider}
% \begin{syntax}
% |input-uncertainty-divider| = \meta{tokens}
% \end{syntax}
% \end{function}
%
% \begin{function}{minimum-decimal-digits}
% \begin{syntax}
% |minimum-decimal-digits| = \meta{min}
Expand Down Expand Up @@ -827,6 +833,7 @@
% \l_siunitx_number_input_exponent_tl ,
% \l_@@_input_ignore_tl ,
% \l_@@_input_uncert_open_tl ,
% \l_@@_input_uncert_divide_tl ,
% \l_siunitx_number_input_sign_tl ,
% \l_@@_input_uncert_sign_tl ,
% \l_@@_explicit_decimal_bool ,
Expand Down Expand Up @@ -868,6 +875,8 @@
{ \tl_put_right:Nn \l_siunitx_number_input_sign_tl {##1} }
}
} ,
input-uncertainty-divider .tl_set:N =
\l_@@_input_uncert_divide_tl ,
parse-numbers .bool_set:N =
\l_siunitx_number_parse_bool ,
retain-explicit-decimal-marker .bool_set:N =
Expand Down Expand Up @@ -941,11 +950,14 @@
% \end{macrocode}
% \end{variable}
%
% \begin{variable}{\l_@@_uncert_tl}
% \begin{variable}{\l_@@_tolerance_tl, \l_@@_uncert_tl, \l_@@_uncert_types_tl}
% To allow multiple uncertainties, we want to build this up as possibly
% multiple entries.
% multiple entries. For asymmetrical uncertainties/tolerances, we need
% an additional store.
% \begin{macrocode}
\tl_new:N \l_@@_tolerance_tl
\tl_new:N \l_@@_uncert_tl
\tl_new:N \l_@@_uncert_types_tl
% \end{macrocode}
% \end{variable}
%
Expand Down Expand Up @@ -1022,6 +1034,7 @@
\group_begin:
\tl_clear:N \l_@@_parsed_tl
\tl_clear:N \l_@@_uncert_tl
\tl_clear:N \l_@@_uncert_types_tl
\tl_map_inline:Nn \l_@@_input_ignore_tl
{
\token_if_macro:NT ##1
Expand Down Expand Up @@ -1606,7 +1619,9 @@
\cs_new_protected:Npn \@@_parse_loop_main_uncert:NN #1#2
{
\@@_parse_loop_main_store:NNN #1 #2 \c_false_bool
\tl_clear:N \l_@@_tolerance_tl
\tl_clear:N \l_@@_uncert_tl
\tl_clear:N \l_@@_uncert_types_tl
\@@_parse_uncert:N
}
% \end{macrocode}
Expand Down Expand Up @@ -1725,8 +1740,13 @@
%
% \begin{macro}{\@@_parse_uncert:N}
% \begin{macro}{\@@_parse_uncert:NNN}
% \begin{macro}{\@@_parse_uncert_auxi:N, \@@_parse_uncert_auxii:N}
% \begin{macro}{\@@_parse_uncert_auxiii:}
% \begin{macro}
% {
% \@@_parse_uncert_auxi:N ,
% \@@_parse_uncert_auxii:N ,
% \@@_parse_uncert_auxiv:N
% }
% \begin{macro}{\@@_parse_uncert_auxiv:}
% \begin{macro}{\@@_parse_uncert_marker:}
% \begin{macro}{\@@_parse_uncert_marker:nnn}
% \begin{macro}{\@@_parse_uncert_marker:nnnw}
Expand Down Expand Up @@ -1784,7 +1804,7 @@
{
\tl_if_in:NnTF \l_siunitx_number_input_decimal_tl {#1}
{ \@@_parse_uncert_marker: }
{ \@@_parse_loop_break:w }
{ \@@_parse_uncert_auxiv:N #1 }
}
}
\cs_new_protected:Npn \@@_parse_uncert_auxii:N #1
Expand All @@ -1794,7 +1814,7 @@
\@@_parse_uncert_auxiii:
\@@_parse_uncert_after:N
}
{ \@@_parse_loop_break:w }
{ \@@_parse_uncert_auxiv:N #1 }
}
% \end{macrocode}
% Deal with the closing bracket, which might leave us with nothing if there
Expand All @@ -1808,6 +1828,24 @@
{ \tl_set:Nn \l_@@_partial_tl { 0 } }
}
% \end{macrocode}
% A common auxiliary for the case where the token is not a digit, a
% decimal mark or a closing parenthesis.
% \begin{macrocode}
\cs_new_protected:Npn \@@_parse_uncert_auxiv:N #1
{
\tl_if_empty:NTF \l_@@_tolerance_tl
{
\tl_if_in:NnTF \l_@@_input_uncert_divide_tl {#1}
{
\cs_set_eq:NN \l_@@_tolerance_tl \l_@@_partial_tl
\tl_clear:N \l_@@_partial_tl
\@@_parse_uncert:N
}
{ \@@_parse_loop_break:w }
}
{ \@@_parse_loop_break:w }
}
% \end{macrocode}
% Handling a decimal marker in the uncertainty is a bit tricky: we need to make
% sure it's valid. First, we need to be sure that the integer part of the captured
% uncertainty is not too long. Then we need to check that the decimal part is
Expand Down Expand Up @@ -1896,9 +1934,26 @@
{
\exp_not:V \l_@@_uncert_tl
\tl_if_empty:NF \l_@@_partial_tl
{ { \exp_not:V \l_@@_partial_tl } }
{
{
\tl_if_empty:NTF \l_@@_tolerance_tl
{ \exp_not:V \l_@@_partial_tl }
{
{ \exp_not:V \l_@@_tolerance_tl }
{ \exp_not:V \l_@@_partial_tl }
}
}
}
}
\tl_set:Nx \l_@@_uncert_types_tl
{
\l_@@_uncert_types_tl
\tl_if_empty:NTF \l_@@_tolerance_tl
{ S }
{ A }
}
\tl_clear:N \l_@@_partial_tl
\tl_clear:N \l_@@_tolerance_tl
\quark_if_recursion_tail_stop_do:Nn #1
{
\tl_set:Nx \l_@@_parsed_tl
Expand All @@ -1907,11 +1962,7 @@
{
\tl_if_empty:NF \l_@@_uncert_tl
{
{
\prg_replicate:nn
{ \tl_count:N \l_@@_uncert_tl }
{ S }
}
{ \l_@@_uncert_types_tl }
\exp_not:V \l_@@_uncert_tl
}
}
Expand Down Expand Up @@ -4727,10 +4778,13 @@
zero-symbol = \mbox { --- }
}
% \end{macrocode}
% One awkward setting.
% Two awkward settings.
% \begin{macrocode}
\keys_set:nx { siunitx }
{ exponent-thresholds = -3 \c_colon_str 3 }
{
exponent-thresholds = -3 \c_colon_str 3 ,
input-uncertainty-divider = \c_colon_str
}
% \end{macrocode}
%
% \begin{macrocode}
Expand Down
9 changes: 9 additions & 0 deletions siunitx.tex
Expand Up @@ -1366,6 +1366,15 @@ \subsection{Parsing numbers}
\num{12.3 +- 6}
\end{LaTeXdemo}

\DescribeOption{input-uncertainty-divider}
In some areas, uncertainties (or tolerances) are given in an asymmetric format.
This is supported in the \enquote{compact} input form in \pkg{siunitx}, with
the positive and negative parts of the uncertainty divided by a symbol listed
in \opt{input-uncertainty-divider}.
\begin{LaTeXdemo}
\num{10.56(12:34)}
\end{LaTeXdemo}

Uncertainties which cross the decimal marker may be given with or without a
decimal marker in \enquote{compact} form. These are treated as equivalent by
the code.\footnote{The package author favors the form without a decimal marker,
Expand Down
29 changes: 29 additions & 0 deletions testfiles/siunitx-number.lvt
Expand Up @@ -103,6 +103,21 @@
\test:n { 123.4 +- 0.0 +- 0.0 }
}

\TEST { Basic~formatting:~asymmetric~uncertainties }
{
\OMIT
\cs_set_protected:Npn \test:n #1
{
\exp_args:Nx \siunitx_number_format:nN { \tl_to_str:n {#1} } \l_tmpa_tl
\tl_show:N \l_tmpa_tl
}
\TIMO
\test:n { 123(4:5) }
\test:n { 123.456(7:8) }
\test:n { 123.45(6:7)(8:9) }
\test:n { 123.5(0:0) }
}

\TEST { Basic~formatting:~comparators }
{
\test:n { > 1.2 }
Expand Down Expand Up @@ -546,6 +561,20 @@
\test:n { 12.34 \pm 5 }
}

\TEST { Option~setting~"input-uncertainty-divider" }
{
\OMIT
\cs_set_protected:Npn \test:n #1
{
\exp_args:Nx \siunitx_number_format:nN { \tl_to_str:n {#1} } \l_tmpa_tl
\tl_show:N \l_tmpa_tl
}
\TIMO
\test:n { 123.4(5:6) }
\keys_set:nn { siunitx } { input-uncertainty-divider = }
\test:n { 123.4(5:6) }
}

\TEST { Option~setting~"minimum-decimal-digits" }
{
\test:n { 1.234 }
Expand Down

0 comments on commit c6a8b7a

Please sign in to comment.