diff options
author | Karl Berry <karl@freefriends.org> | 2022-04-25 20:23:16 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2022-04-25 20:23:16 +0000 |
commit | 77138a64eb620d96c69f875fe8343ca5fd541ada (patch) | |
tree | 75d19935c84604c6757c9666f0d12b28258a0ee7 /Master | |
parent | df9eafcf47f1c04aeec4fd35a59fd2e5893355e8 (diff) |
siunitx (25apr22)
git-svn-id: svn://tug.org/texlive/trunk@63138 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master')
15 files changed, 3452 insertions, 1282 deletions
diff --git a/Master/texmf-dist/doc/latex/siunitx/CHANGELOG.md b/Master/texmf-dist/doc/latex/siunitx/CHANGELOG.md index cec77aae345..c0810e829bd 100644 --- a/Master/texmf-dist/doc/latex/siunitx/CHANGELOG.md +++ b/Master/texmf-dist/doc/latex/siunitx/CHANGELOG.md @@ -7,6 +7,46 @@ Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to ## [Unreleased] +## [v3.1.0] - 2022-04-25 + +### Added +- Support for complex numbers in polar form both as input and output +- Support for multiple uncertainty values in both short and long form + in input, and supporting options `uncertainty-descriptors`, + `uncertainty-descriptor-mode` and `uncertainty-descriptor-separator` +- Options `text-subscript-command` and `text-superscript-command` to allow + customisation of script printing in text mode (see issue + [\#595](https://github.com/josephwright/siunitx/issues/595)) +- Options `complex-angle-unit`, `complex-mode`, `complex-symbol-angle`, + and `complex-symbol-degree` to support complex numbers in polar form +- Options `digit-group-size`, `digit-group-first-size` and + `digit-group-other-size` to control digit grouping +- Options `display-per-mode` and `inline-per-mode` to offer additional + flexiblity in `per-mode` control +- Option `per-symbol-script-correction` +- Option `power-half-as-sqrt` +- Option `retain-negative-zero` +- Option `round-zero-positive` to control the outcome of rounding + negative values to zero +- Options `zero-decimal-as-symbol` and `zero-symbol` to support conversion of + a zero decimal part to a dash or other symbol +- Option setting `per-mode = single-symbol` to allow exactly one symbol to be + present +- Unit abbreviations `\C`, `\nC`, `\uC`, `\mC` (see issue + [\#575](https://github.com/josephwright/siunitx/issues/575)) +- Unit abbreviations `\fH` and `\pH` (see issue + [\#596](https://github.com/josephwright/siunitx/issues/596)) +- Unit abbreviation `\nW` (see issue + [\#596](https://github.com/josephwright/siunitx/issues/596)) +- Brazilian and Portuguese translations for lists and ranges (see issue + [\#514](https://github.com/josephwright/siunitx/issues/514)) + +### Changed +- Issue an error if the `units` package is loaded + +### Deprecated +- Option setting `per-mode = symbol-or-fraction` + ## [v3.0.50] - 2022-04-04 ### Fixed @@ -1729,7 +1769,8 @@ Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to ### Added - First public testing release (as `si`) -[Unreleased]: https://github.com/josephwright/siunitx/compare/v3.0.50...HEAD +[Unreleased]: https://github.com/josephwright/siunitx/compare/v3.1.0...HEAD +[v3.1.0]: https://github.com/josephwright/siunitx/compare/v3.0.50...v3.1.0 [v3.0.50]: https://github.com/josephwright/siunitx/compare/v3.0.49...v3.0.50 [v3.0.49]: https://github.com/josephwright/siunitx/compare/v3.0.48...v3.0.49 [v3.0.48]: https://github.com/josephwright/siunitx/compare/v3.0.47...v3.0.48 diff --git a/Master/texmf-dist/doc/latex/siunitx/siunitx-code.pdf b/Master/texmf-dist/doc/latex/siunitx/siunitx-code.pdf Binary files differindex 6b05035a14d..a91ddf0a367 100644 --- a/Master/texmf-dist/doc/latex/siunitx/siunitx-code.pdf +++ b/Master/texmf-dist/doc/latex/siunitx/siunitx-code.pdf diff --git a/Master/texmf-dist/doc/latex/siunitx/siunitx.pdf b/Master/texmf-dist/doc/latex/siunitx/siunitx.pdf Binary files differindex f66535f7ea6..0f234b75d97 100644 --- a/Master/texmf-dist/doc/latex/siunitx/siunitx.pdf +++ b/Master/texmf-dist/doc/latex/siunitx/siunitx.pdf diff --git a/Master/texmf-dist/source/latex/siunitx/siunitx-abbreviation.dtx b/Master/texmf-dist/source/latex/siunitx/siunitx-abbreviation.dtx index 9fc5ddb2a52..debc9f2a6b9 100644 --- a/Master/texmf-dist/source/latex/siunitx/siunitx-abbreviation.dtx +++ b/Master/texmf-dist/source/latex/siunitx/siunitx-abbreviation.dtx @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% File: siunitx-abbreviation.dtx Copyright (C) 2018,2019 Joseph Wright +% File: siunitx-abbreviation.dtx Copyright (C) 2018,2019,2021,2022 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 @@ -94,7 +94,7 @@ % Abbreviations for volumes. % \end{function} % -% \begin{function}{\W, \uW, \mW, \kW, \MW, \GW} +% \begin{function}{\W, \nW, \uW, \mW, \kW, \MW, \GW} % Abbreviations for powers. % \end{function} % @@ -118,6 +118,14 @@ % Abbreviations for capacitance. % \end{function} % +% \begin{function}{\H, \fH, \pH, \nH, \uH, \mH} +% Abbreviations for inductance. +% \end{function} +% +% \begin{function}{\C, \nC \uC, \mC} +% Abbreviations for charge. +% \end{function} +% % \begin{function}{\dB} % Abbreviation for decibel. % \end{function} @@ -214,7 +222,7 @@ % \end{macro} % \begin{macro} % { -% \W, \uW, \mW, \kW, \MW, \GW, +% \W, \nW, \uW, \mW, \kW, \MW, \GW, % \kJ, \J, \mJ, \uJ, % \eV, \meV, \keV, \MeV, \GeV, \TeV, % \kWh @@ -222,6 +230,7 @@ % Energies and powers % \begin{macrocode} \siunitx_declare_unit:Nn \W { \watt } +\siunitx_declare_unit:Nn \nW { \nano \watt } \siunitx_declare_unit:Nn \uW { \micro \watt } \siunitx_declare_unit:Nn \mW { \milli \watt } \siunitx_declare_unit:Nn \kW { \kilo \watt } @@ -275,12 +284,24 @@ \siunitx_declare_unit:Nn \uF { \micro \farad } % \end{macrocode} % \end{macro} -% \begin{macro}{\H, \mH, \uH} -% Capacitance. +% \begin{macro}{\H, \fH, \pH, \nH, \uH, \mH} +% Inductance. +% \begin{macrocode} +\siunitx_declare_unit:Nn \H { \henry } +\siunitx_declare_unit:Nn \fH { \femto \henry } +\siunitx_declare_unit:Nn \pH { \pico \henry } +\siunitx_declare_unit:Nn \nH { \nano \henry } +\siunitx_declare_unit:Nn \uH { \micro \henry } +\siunitx_declare_unit:Nn \mH { \milli \henry } +% \end{macrocode} +% \end{macro} +% \begin{macro}{\C, \nC, \uC, \mC} +% Charge. % \begin{macrocode} -\siunitx_declare_unit:Nn \H { \henry } -\siunitx_declare_unit:Nn \mH { \milli \henry } -\siunitx_declare_unit:Nn \uH { \micro \henry } +\siunitx_declare_unit:Nn \C { \coulomb } +\siunitx_declare_unit:Nn \nC { \nano \coulomb } +\siunitx_declare_unit:Nn \uC { \micro \coulomb } +\siunitx_declare_unit:Nn \mC { \milli \coulomb } % \end{macrocode} % \end{macro} % \begin{macro}{\N, \mN, \kN, \MN} diff --git a/Master/texmf-dist/source/latex/siunitx/siunitx-code.tex b/Master/texmf-dist/source/latex/siunitx/siunitx-code.tex index bf2bd1b7e9f..a4c39783107 100644 --- a/Master/texmf-dist/source/latex/siunitx/siunitx-code.tex +++ b/Master/texmf-dist/source/latex/siunitx/siunitx-code.tex @@ -1,6 +1,6 @@ \iffalse meta-comment -File: siunitx-code.tex Copyright (C) 2016-2021 Joseph Wright +File: siunitx-code.tex Copyright (C) 2016-2022 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 @@ -34,9 +34,19 @@ for those people who are interested. % Commands for this document \ExplSyntaxOn -\cs_new_eq:NN \LowerCaseText \tl_lower_case:n +\makeatletter +\NewDocumentCommand \acro { m } + { + \textsc + { + \exp_args:NV \tl_if_head_eq_charcode:nNTF \f@series { m } + { \text_lowercase:n } + { \use:n } + {#1} + } + } +\makeatother \ExplSyntaxOff -\NewDocumentCommand\acro{m}{\textsc{\LowerCaseText{#1}}} \NewDocumentCommand\foreign{m}{\textit{#1}} % Standard settings diff --git a/Master/texmf-dist/source/latex/siunitx/siunitx-complex.dtx b/Master/texmf-dist/source/latex/siunitx/siunitx-complex.dtx index d81e27f4ac8..9cd595d28f3 100644 --- a/Master/texmf-dist/source/latex/siunitx/siunitx-complex.dtx +++ b/Master/texmf-dist/source/latex/siunitx/siunitx-complex.dtx @@ -71,16 +71,59 @@ % \end{syntax} % Parses the \meta{number} and splits into real and complex parts, which are % then formatted as described for \cs{siunitx_number_format:nN}. The results -% are combined and printed using the standard functions in the module. +% are combined and printed using the standard functions in the module. If +% the setting \opt{complex-mode} is set to \meta{polar}, the input is +% parsed, converted to polar form and then passed to +% \cs{siunitx_complex_number:nn}. This parsing requires that the complex root +% is given as \texttt{i} at the \emph{end} of the value. % \end{function} % -% \begin{function}{\siunitx_complex_quantity:nn} +% \begin{function}{\siunitx_complex_number:nn} % \begin{syntax} -% \cs{siunitx_complex_quantity:n} \Arg{number} \Arg{units} +% \cs{siunitx_complex_number:nn} \Arg{magnitude} \Arg{angle} % \end{syntax} -% Parses the \meta{number} and splits into real and complex parts, which are -% then formatted as described for \cs{siunitx_quantity:nn}. The results -% are combined and printed using the standard functions in the module. +% Parses the \meta{magnitude} and \meta{angle} and then formats each as +% described for \cs{siunitx_number_format:nN}. The two are separated by the +% angle symbol, which is treated as a numerical part. If +% \opt{complex-angle-unit} is set to \opt{degrees} then the unit symbol is +% added: this is printed as a unit in the usual way. If +% the setting \opt{complex-mode} is set to \meta{cartesian}, the input is +% parsed, converted to Cartesian form and then passed to +% \cs{siunitx_complex_number:n}. +% \end{function} +% +% \begin{function}{\siunitx_complex_quantity:nn, \siunitx_complex_quantity:nnn} +% \begin{syntax} +% \cs{siunitx_complex_quantity:nn} \Arg{number} \Arg{units} +% \cs{siunitx_complex_quantity:nnn} \Arg{magnitude} \Arg{angle} \Arg{units} +% \end{syntax} +% These functions treat their numerical argument(s) as described +% for the corresponding \texttt{number} functions. They then typeset the +% entire numerical part and the unit as described for \cs{siunitx_quantity:nn}. +% \end{function} +% +% \begin{function}{complex-angle-unit} +% \begin{syntax} +% |complex-angle-unit| = |degrees|\verb"|"|radians| +% \end{syntax} +% Sets how the unit for polar complex numbers is treated. This setting +% is used to determine how polar \emph{input} is interpreted, how +% conversion to polar form works and how output in polar form is typeset. +% The standard setting is |degrees|. +% \end{function} +% +% \begin{function}{complex-mode} +% \begin{syntax} +% |complex-mode| = |cartesian|\verb"|"|input|\verb"|"|polar| +% \end{syntax} +% Selects how complex values are formatted: a choice from the options +% |cartesian|, |input| and |polar|. The option |cartesian| means that +% complex values will always be typeset in cartesian ($x + y\mathrm{i}$) +% format, whilst |polar| means that complex are typeset as a magnitude +% and angle. Finally, |input| setting means that the input format +% (\foreign{i.e.}~difference between \cs{siunitx_complex_number:n} and +% \cs{siunitx_complex_number:nn}) is maintained. The standard setting is +% |input|. % \end{function} % % \begin{function}{complex-root-position} @@ -91,6 +134,20 @@ % to the numbers. The standard setting is |after-number|. % \end{function} % +% \begin{function}{complex-symbol-angle} +% \begin{syntax} +% |complex-symbol-angle| = \meta{symbol} +% \end{syntax} +% Sets the symbol used before the polar angle. +% \end{function} +% +% \begin{function}{complex-symbol-degree} +% \begin{syntax} +% |complex-symbol-degree| = \meta{symbol} +% \end{syntax} +% Sets the symbol used for polar degrees. +% \end{function} +% % \begin{function}{input-complex-root} % \begin{syntax} % |input-complex-root| = \meta{tokens} @@ -155,13 +212,21 @@ % \end{variable} % % \begin{variable}{\l_@@_real_tl, \l_@@_img_tl} -% The real and imaginary parts of the number, respectively. +% The real and imaginary parts of cartesian form, respectively. % \begin{macrocode} \tl_new:N \l_@@_real_tl \tl_new:N \l_@@_img_tl % \end{macrocode} % \end{variable} % +% \begin{variable}{\l_@@_mag_tl, \l_@@_angle_tl} +% The magnitude and angle of polar form, respectively. +% \begin{macrocode} +\tl_new:N \l_@@_mag_tl +\tl_new:N \l_@@_angle_tl +% \end{macrocode} +% \end{variable} +% % \begin{variable}{\l_@@_join_tl, \l_@@_sign_tl} % Staging posts for a joining and leading sign, respectively. % \begin{macrocode} @@ -170,16 +235,54 @@ % \end{macrocode} % \end{variable} % -% \begin{variable}{\l_@@_input_root_tl, \l_@@_output_root_tl} +% \begin{variable} +% { +% \l_@@_root_after_bool , +% \l_@@_force_cartesian_bool , +% \l_@@_force_polar_bool , +% \l_@@_polar_degree_bool , +% \l_@@_symbol_angle_tl , +% \l_@@_symbol_degree_tl , +% \l_@@_input_root_tl , +% \l_@@_output_root_tl +% } % \begin{macrocode} \bool_new:N \l_@@_root_after_bool +\bool_new:N \l_@@_force_cartesian_bool +\bool_new:N \l_@@_force_polar_bool +\bool_new:N \l_@@_polar_degree_bool \keys_define:nn { siunitx } { + complex-mode .choice: , + complex-mode / cartesian .code:n = + { + \bool_set_true:N \l_@@_force_cartesian_bool + \bool_set_false:N \l_@@_force_polar_bool + } , + complex-mode / polar .code:n = + { + \bool_set_false:N \l_@@_force_cartesian_bool + \bool_set_true:N \l_@@_force_polar_bool + } , + complex-mode / input .code:n = + { + \bool_set_false:N \l_@@_force_cartesian_bool + \bool_set_false:N \l_@@_force_polar_bool + } , + complex-angle-unit .choice: , + complex-angle-unit / degrees .code:n = + { \bool_set_true:N \l_@@_polar_degree_bool } , + complex-angle-unit / radians .code:n = + { \bool_set_false:N \l_@@_polar_degree_bool } , complex-root-position .choice: , complex-root-position / after-number .code:n = { \bool_set_true:N \l_@@_root_after_bool } , complex-root-position / before-number .code:n = { \bool_set_false:N \l_@@_root_after_bool } , + complex-symbol-angle .tl_set:N = + \l_@@_symbol_angle_tl , + complex-symbol-degree .tl_set:N = + \l_@@_symbol_degree_tl , input-complex-root .tl_set:N = \l_@@_input_root_tl , output-complex-root .tl_set:N = @@ -232,40 +335,26 @@ % \end{macro} % \end{macro} % -% \begin{macro}{\@@_parse_check:, \@@_parse_finalise:} -% \begin{macro}{\@@_parse_finalise:N} +% \begin{macro}{\@@_parse_check:} +% \begin{macro}{\@@_parse_check:N} % Now we tidy up and do the main work: passing to the standard formatter for % final parsing. % \begin{macrocode} \cs_new_protected:Npn \@@_parse_check: { - \bool_lazy_all:nTF - { - { \tl_if_empty_p:N \l_@@_real_tl } - { \tl_if_empty_p:N \l_@@_img_tl } - { \tl_if_empty_p:N \l_@@_exp_tl } - } - { - \msg_error:nnx { siunitx } { invalid-complex-number } - { \exp_not:V \l_@@_input_tl } - } - { \@@_parse_finalise: } - } -\cs_new_protected:Npn \@@_parse_finalise: - { \tl_if_empty:NTF \l_@@_img_tl - { \@@_parse_finalise:N \l_@@_real_tl } + { \@@_parse_check:N \l_@@_real_tl } { \tl_if_empty:NTF \l_@@_real_tl - { \@@_parse_finalise:N \l_@@_img_tl } + { \@@_parse_check:N \l_@@_img_tl } { - \@@_parse_finalise:N \l_@@_real_tl + \@@_parse_check:N \l_@@_real_tl \tl_set_eq:NN \l_@@_sign_tl \l_@@_join_tl - \@@_parse_finalise:N \l_@@_img_tl + \@@_parse_check:N \l_@@_img_tl } } } -\cs_new_protected:Npn \@@_parse_finalise:N #1 +\cs_new_protected:Npn \@@_parse_check:N #1 { \tl_set:Nx #1 { @@ -545,6 +634,27 @@ % \end{macro} % \end{macro} % +% \begin{macro}{\@@_parse_polar:nn} +% Almost trivial but repeated in a couple of places so worth an auxiliary. +% \begin{macrocode} +\cs_new_protected:Npn \@@_parse_polar:nn #1#2 + { + \siunitx_number_parse:nN {#1} \l_@@_mag_tl + \group_begin: + \keys_set:nn { siunitx } + { + input-comparators = , + input-exponent-markers = , + input-open-uncertainty = , + input-close-uncertainty = + } + \siunitx_number_format:nN {#2} \l_@@_angle_tl + \exp_args:NNNV \group_end: + \tl_set:Nn \l_@@_angle_tl \l_@@_angle_tl + } +% \end{macrocode} +% \end{macro} +% % \section{Formatting} % % \begin{variable}{\l_@@_bracket_close_tl, \l_@@_bracket_open_tl} @@ -564,41 +674,110 @@ % \end{variable} % % \begin{macro}{\siunitx_complex_number:n} +% \begin{macro}{\siunitx_complex_number:nn, \@@_number:nn} % \begin{macro}{\siunitx_complex_quantity:nn} -% The work here is pretty trivial. +% \begin{macro}{\siunitx_complex_quantity:nnn, \@@_quantity:nnn} +% The work here is pretty trivial: only conversion between forms makes +% things a bit more intricate. % \begin{macrocode} \cs_new_protected:Npn \siunitx_complex_number:n #1 { - \group_begin: - \bool_if:NTF \l_siunitx_number_parse_bool - { - \@@_parse:nNN {#1} \l_@@_real_tl \l_@@_img_tl - \@@_format:n { } - } - { - \siunitx_number_format:nN {#1} \l_@@_tmp_tl - \siunitx_print_number:V \l_@@_tmp_tl - } - \group_end: + \bool_if:NTF \l_@@_force_polar_bool + { + \use:e + { + \siunitx_complex_number:nn + \@@_convert_polar:n {#1} + } + } + { + \bool_if:NTF \l_siunitx_number_parse_bool + { + \@@_parse:nNN {#1} \l_@@_real_tl \l_@@_img_tl + \@@_format_cartesian:n { } + } + { + \siunitx_number_format:nN {#1} \l_@@_tmp_tl + \siunitx_print_number:V \l_@@_tmp_tl + } + } + } +\cs_new_protected:Npn \siunitx_complex_number:nn #1#2 + { + \bool_lazy_or:nnTF + { \tl_if_blank_p:n {#1} } + { \tl_if_blank_p:n {#2} } + { + \msg_error:nnnn { siunitx } { invalid-polar-form } + {#1} {#2} + } + { \@@_number:nn {#1} {#2} } + } +\cs_new_protected:Npn \@@_number:nn #1#2 + { + \bool_if:NTF \l_@@_force_cartesian_bool + { + \exp_args:Ne \siunitx_complex_number:n + { \@@_convert_cartesian:nn {#1} {#2} } + } + { + \@@_parse_polar:nn {#1} {#2} + \@@_format_polar:n { } + } } \cs_new_protected:Npn \siunitx_complex_quantity:nn #1#2 { - \group_begin: - \bool_if:NTF \l_siunitx_number_parse_bool - { - \@@_parse:nNN {#1} \l_@@_real_tl \l_@@_img_tl - \@@_format:n {#2} - } - { \siunitx_quantity:nn {#1} {#2} } - \group_end: + \bool_if:NTF \l_@@_force_polar_bool + { + \use:e + { + \siunitx_complex_quantity:nnn + \@@_convert_polar:n {#1} + } + {#2} + } + { + \bool_if:NTF \l_siunitx_number_parse_bool + { + \@@_parse:nNN {#1} \l_@@_real_tl \l_@@_img_tl + \@@_format_cartesian:n {#2} + } + { \siunitx_quantity:nn {#1} {#2} } + } + } +\cs_new_protected:Npn \siunitx_complex_quantity:nnn #1#2#3 + { + \bool_lazy_or:nnTF + { \tl_if_blank_p:n {#1} } + { \tl_if_blank_p:n {#2} } + { + \msg_error:nnnn { siunitx } { invalid-polar-form } + {#1} {#2} + } + { \@@_quantity:nnn {#1} {#2} {#3} } + } +\cs_new_protected:Npn \@@_quantity:nnn #1#2#3 + { + \bool_if:NTF \l_@@_force_cartesian_bool + { + \exp_args:Ne \siunitx_complex_quantity:nn + { \@@_convert_cartesian:nn {#1} {#2} } + {#3} + } + { + \@@_parse_polar:nn {#1} {#2} + \@@_format_polar:n {#3} + } } % \end{macrocode} % \end{macro} % \end{macro} +% \end{macro} +% \end{macro} % -% \begin{macro}{\@@_format:n} -% \begin{macro}{\@@_format_auxi:n} -% \begin{macro}{\@@_format_auxii:n} +% \begin{macro}{\@@_format_cartesian:n} +% \begin{macro}{\@@_format_cartesian_auxi:n} +% \begin{macro}{\@@_format_cartesian_auxii:n} % \begin{macro}{\@@_drop_exponent:nnnnnnn} % \begin{macro}{\@@_format_sign:nnnnnnn} % \begin{macro}{\@@_extract_exponent:nw} @@ -606,18 +785,18 @@ % \begin{macro}[EXP]{\@@_format_bracket:n} % We start here checking that there is something to do. % \begin{macrocode} -\cs_new_protected:Npn \@@_format:n #1 +\cs_new_protected:Npn \@@_format_cartesian:n #1 { \bool_lazy_and:nnF { \tl_if_empty_p:N \l_@@_real_tl } { \tl_if_empty_p:N \l_@@_img_tl } - { \@@_format_auxi:n {#1} } + { \@@_format_cartesian_auxi:n {#1} } } % \end{macrocode} % We split based on whether the number has a complex part at all, % then print the result. % \begin{macrocode} -\cs_new_protected:Npn \@@_format_auxi:n #1 +\cs_new_protected:Npn \@@_format_cartesian_auxi:n #1 { \tl_clear:N \l_@@_tmp_tl \tl_if_empty:NTF \l_@@_img_tl @@ -626,7 +805,7 @@ \tl_set:Nx \l_@@_tmp_tl { \siunitx_number_output:N \l_@@_real_tl } } - { \@@_format_auxii:n {#1} } + { \@@_format_cartesian_auxii:n {#1} } \tl_if_blank:nTF {#1} { \siunitx_print_number:V \l_@@_tmp_tl } { \siunitx_quantity_print:VV \l_@@_tmp_tl \l_@@_unit_tl } @@ -636,9 +815,9 @@ % need to process both and do some massaging, then it's just a question % of reassembly with the right parts in the right places. % \begin{macrocode} -\cs_new_protected:Npn \@@_format_auxii:n #1 +\cs_new_protected:Npn \@@_format_cartesian_auxii:n #1 { - \@@_format_units:n {#1} + \@@_format_cartesian_units:n {#1} \tl_if_empty:NF \l_@@_real_tl { \exp_after:wN \@@_drop_exponent:nnnnnnn \l_@@_real_tl } \exp_after:wN \@@_format_sign:nnnnnnn \l_@@_img_tl @@ -744,12 +923,12 @@ % \end{macro} % \end{macro} % -% \begin{macro}{\@@_format_units:n} +% \begin{macro}{\@@_format_cartesian_units:n} % \begin{macro} % { -% \@@_format_combine-exponent:n , -% \@@_format_extract-exponent:n , -% \@@_format_input:n +% \@@_format_cartesian_combine-exponent:n , +% \@@_format_cartesian_extract-exponent:n , +% \@@_format_cartesian_input:n % } % \begin{macro}{\@@_format_extract-exponent:N} % \begin{macro}[EXP]{\@@_extract_exp:nnnnnnn} @@ -759,7 +938,7 @@ % the flow is then much the same as in \pkg{siunitx-compound}. We only % have to watch the fact there are two numbers to format. % \begin{macrocode} -\cs_new_protected:Npn \@@_format_units:n #1 +\cs_new_protected:Npn \@@_format_cartesian_units:n #1 { \tl_if_blank:nTF {#1} { @@ -767,10 +946,11 @@ \siunitx_number_process:NN \l_@@_img_tl \l_@@_img_tl } { - \use:c { @@_format_ \l_siunitx_quantity_prefix_mode_tl :n } {#1} + \use:c + { @@_format_cartesian_ \l_siunitx_quantity_prefix_mode_tl :n } {#1} } } -\cs_new_protected:cpn { @@_format_combine-exponent:n } #1 +\cs_new_protected:cpn { @@_format_cartesian_combine-exponent:n } #1 { \tl_if_empty:NF \l_@@_real_tl { \siunitx_number_process:NN \l_@@_real_tl \l_@@_real_tl } @@ -782,7 +962,7 @@ \siunitx_unit_format_combine_exponent:nnN {#1} \l_@@_tmp_fp \l_@@_unit_tl } -\cs_new_protected:cpx { @@_format_extract-exponent:n } #1 +\cs_new_protected:cpx { @@_format_cartesian_extract-exponent:n } #1 { \exp_not:N \siunitx_unit_format_extract_prefixes:nNN {#1} \exp_not:N \l_@@_unit_tl \exp_not:N \l_@@_tmp_fp @@ -794,18 +974,18 @@ \exp_not:N \l_@@_real_tl } } +\cs_new_protected:Npn \@@_format_cartesian_input:n #1 + { + \siunitx_number_process:NN \l_@@_real_tl \l_@@_real_tl + \siunitx_number_process:NN \l_@@_img_tl \l_@@_img_tl + \siunitx_unit_format:nN {#1} \l_@@_unit_tl + } \cs_new_protected:cpn { @@_format_extract-exponent:N } #1 { \tl_set:Nx #1 { \siunitx_number_adjust_exponent:Nn #1 \l_@@_tmp_fp } \siunitx_number_process:NN #1 #1 } -\cs_new_protected:Npn \@@_format_input:n #1 - { - \siunitx_number_process:NN \l_@@_real_tl \l_@@_real_tl - \siunitx_number_process:NN \l_@@_img_tl \l_@@_img_tl - \siunitx_unit_format:nN {#1} \l_@@_unit_tl - } \cs_new:Npn \@@_extract_exp:nnnnnnn #1#2#3#4#5#6#7 { #6#7 } \cs_new_protected:Npn \@@_drop_exp:N #1 { \exp_after:wN \@@_drop_exp:nnnnnnnN #1 #1 } @@ -819,14 +999,196 @@ % \end{macro} % \end{macro} % +% \begin{macro} +% { +% \@@_format_polar:n , +% \@@_format_combine-exponent:n , +% \@@_format_extract-exponent:n , +% \@@_format_polar_input:n +% } +% We see similar ideas here to the Cartesian versions, but with only +% the magnitude to adjust, things are rather simpler in the exponent +% manipulations. +% \begin{macrocode} +\cs_new_protected:Npn \@@_format_polar:n #1 + { + \tl_if_blank:nTF {#1} + { \siunitx_number_process:NN \l_@@_mag_tl \l_@@_mag_tl } + { + \use:c + { @@_format_polar_ \l_siunitx_quantity_prefix_mode_tl :n } {#1} + } + \tl_set:Nx \l_@@_tmp_tl + { + \siunitx_number_output:N \l_@@_mag_tl + \exp_not:V \l_@@_symbol_angle_tl + \mathord % TEMP + \exp_not:V \l_@@_angle_tl + } + \siunitx_print_number:V \l_@@_tmp_tl + \bool_if:NT \l_@@_polar_degree_bool + { + \exp_args:NV \siunitx_unit_format:nN \l_@@_symbol_degree_tl \l_@@_tmp_tl + \nobreak + \siunitx_print_unit:V \l_@@_tmp_tl + } + \siunitx_quantity_print:nV { } \l_@@_unit_tl + } +\cs_new_protected:cpn { @@_format_polar_combine-exponent:n } #1 + { + \siunitx_number_process:NN \l_@@_mag_tl \l_@@_mag_tl + \fp_set:Nn \l_@@_tmp_fp + { \exp_after:wN \@@_extract_exp:nnnnnnn \l_@@_mag_tl } + \@@_drop_exp:N \l_@@_mag_tl + \siunitx_unit_format_combine_exponent:nnN {#1} + \l_@@_tmp_fp \l_@@_unit_tl + } +\cs_new_protected:cpx { @@_format_polar_extract-exponent:n } #1 + { + \exp_not:N \siunitx_unit_format_extract_prefixes:nNN {#1} + \exp_not:N \l_@@_unit_tl \exp_not:N \l_@@_tmp_fp + \exp_not:c { @@_format_extract-exponent:N } + \exp_not:N \l_@@_mag_tl + } +\cs_new_protected:Npn \@@_format_polar_input:n #1 + { + \siunitx_number_process:NN \l_@@_mag_tl \l_@@_mag_tl + \siunitx_unit_format:nN {#1} \l_@@_unit_tl + } +% \end{macrocode} +% \end{macro} +% +% \subsection{Conversion} +% +% \begin{macro}[EXP] +% {\@@_convert_cartesian:nn, \@@_convert_cartesian_aux:nn} +% \begin{macro}[EXP]{\@@_convert_cartesian_aux:w} +% Conversion to Cartesian form is easy as we have two inputs and need to +% do no parsing here at all. +% \begin{macrocode} +\cs_new:Npn \@@_convert_cartesian:nn #1#2 + { + \exp_args:Nee \@@_convert_cartesian_aux:nn + { + \fp_to_tl:n + { (#1) * cos \bool_if:NT \l_@@_polar_degree_bool { d } (#2) } + } + { + \fp_to_tl:n + { (#1) * sin \bool_if:NT \l_@@_polar_degree_bool { d } (#2) } + } + } +\cs_new:Npn \@@_convert_cartesian_aux:nn #1#2 + { + \@@_convert_cartesian_aux:w #1 e e \q_mark #2 e e \q_stop + } +\cs_new:Npn \@@_convert_cartesian_aux:w + #1 e #2 e #3 \q_mark #4 e #5 e #6 \q_stop + { + \fp_compare:nNnF {#1} = \c_zero_fp + {#1} + \fp_compare:nNnF {#4} = \c_zero_fp + { + \fp_compare:nNnF {#4} < \c_zero_fp { + } + #4 i + } + \tl_if_blank:nF {#2} + { e #2 } + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}[EXP]{\@@_convert_polar:n} +% \begin{macro}[EXP]{\@@_convert_polar_auxi:w} +% \begin{macro}[EXP]{\@@_convert_polar_auxii:nw} +% \begin{macro}[EXP]{\@@_convert_polar_auxiii:nnw} +% \begin{macro}[EXP]{\@@_convert_polar_auxiv:nnw} +% \begin{macro}[EXP]{\@@_convert_polar_auxv:nnw} +% \begin{macro}[EXP]{\@@_convert_polar_auxvi:nnn} +% \begin{macro}[EXP]{\@@_convert_polar_auxvii:nnn} +% \begin{macro}[EXP]{\@@_convert_polar_auxviii:nn} +% A simplified parser for complex numbers which works by expansion, +% then converts to polar form. +% \begin{macrocode} +\cs_new:Npn \@@_convert_polar:n #1 + { \@@_convert_polar_auxi:w #1 e e \q_stop } +\cs_new:Npn \@@_convert_polar_auxi:w #1 e #2 e #3 \q_stop + { \@@_convert_polar_auxii:nw {#2} #1 \q_stop } +\cs_new:Npn \@@_convert_polar_auxii:nw #1#2#3 \q_stop + { + \bool_lazy_or:nnTF + { \str_if_eq_p:nn {#2} { i } } + { \str_if_eq_p:nn {#2#3} { +i } } + { \@@_convert_polar_auxvi:nnn { } { 1 } {#1} } + { + \str_if_eq:nnTF {#2#3} { -i } + { \@@_convert_polar_auxvi:nnn { } { -1 } {#1} } + { \@@_convert_polar_auxiii:nnw {#1} {#2} #3 + + \q_stop } + } + } +\cs_new:Npn \@@_convert_polar_auxiii:nnw #1#2#3 + #4 + #5 \q_stop + { + \tl_if_blank:nTF {#4} + { \@@_convert_polar_auxiv:nnw {#1} {#2} #3 - - \q_stop } + { + \str_if_eq:nnTF {#4} { i } + { \@@_convert_polar_auxvi:nnn {#2#3} { 1 } {#1} } + { \@@_convert_polar_auxv:nnw {#2#3} {#1} #4 i \q_nil i \q_stop } + } + } +\cs_new:Npn \@@_convert_polar_auxiv:nnw #1#2#3 - #4 - #5 \q_stop + { + \tl_if_blank:nTF {#4} + { \@@_convert_polar_auxv:nnw { } {#1} #2#3 i \q_nil i \q_stop } + { + \str_if_eq:nnTF {#4} { i } + { \@@_convert_polar_auxvi:nnn { } { -1 } {#1} } + { \@@_convert_polar_auxv:nnw {#2#3} {#1} -#4 i \q_nil i \q_stop } + } + } +\cs_new:Npn \@@_convert_polar_auxv:nnw #1#2#3 i #4 i #5 \q_stop + { + \quark_if_nil:nTF {#4} + { { #3 \tl_if_blank:nF {#2} { e#2 } } { 0 } } + { \@@_convert_polar_auxvi:nnn {#1} {#3} {#2} } + } +\cs_new:Npn \@@_convert_polar_auxvi:nnn #1#2#3 + { + \exp_args:Neee \@@_convert_polar_auxvii:nnn + { \tl_if_blank:nTF {#1} { 0 } {#1} } + { \tl_if_blank:nTF {#2} { 0 } {#2} } + { \tl_if_blank:nF {#3} { e#3 } } + } +\cs_new:Npn \@@_convert_polar_auxvii:nnn #1#2#3 + { + \exp_args:Nee \@@_format_polar_auxviii:nn + { \fp_eval:n { sqrt ( (#1#3)^2 + (#2#3)^2 ) } } + { + \fp_eval:n + { atan \bool_if:NT \l_@@_polar_degree_bool { d } (#2 , #1) } + } + } +\cs_new:Npn \@@_format_polar_auxviii:nn #1#2 { {#1} {#2} } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% % \subsection{Messages} % % \begin{macrocode} -\msg_new:nnnn { siunitx } { invalid-complex-number } - { Invalid~complex-number~'#1'. } +\msg_new:nnnn { siunitx } { invalid-polar-form } + { Invalid~polar~form~"#1:#2". } { - The~input~'#1'~could~not~be~parsed~as~a~complex|number~following~the~ - format~defined~in~module~documentation. + Complex~numbers~in~polar~form~must~have~both~a~magnitude~and~and~ + angle. } % \end{macrocode} % @@ -838,7 +1200,11 @@ % \begin{macrocode} \keys_set:nn { siunitx } { + complex-angle-unit = degrees , + complex-mode = input , complex-root-position = after-number , + complex-symbol-angle = \angle , + complex-symbol-degree = \degree , input-complex-root = ij , output-complex-root = \mathrm { i } } diff --git a/Master/texmf-dist/source/latex/siunitx/siunitx-emulation.dtx b/Master/texmf-dist/source/latex/siunitx/siunitx-emulation.dtx index aab7d478f25..1b96dd2b9a5 100644 --- a/Master/texmf-dist/source/latex/siunitx/siunitx-emulation.dtx +++ b/Master/texmf-dist/source/latex/siunitx/siunitx-emulation.dtx @@ -82,11 +82,6 @@ % % Some messages. % \begin{macrocode} -\msg_new:nnn { siunitx } { option-deprecated } - { - Option~"#1"~has~been~deprecated~in~this~release.\\ \\ - Use~"#2"~as~a~replacement. - } \msg_new:nnn { siunitx } { option-removed } { Option~"#1"~has~been~removed~in~this~release. } % \end{macrocode} @@ -97,13 +92,17 @@ % \begin{macrocode} \cs_new_protected:Npn \@@_option_deprecated:nn #1#2 { - \msg_info:nnnn { siunitx } { option-deprecated } {#1} {#2} + \@@_deprecated_info:nn {#1} {#2} \keys_set:nn { siunitx } {#2} } \cs_new_protected:Npn \@@_option_deprecated:nnn #1#2#3 { - \msg_info:nnnn { siunitx } { option-deprecated } {#1} {#2} - \keys_set:nn { siunitx } { #2 = #3 } + \str_if_eq:nnTF {#3} { true } + { \@@_option_deprecated:nn {#1} {#2} } + { + \@@_deprecated_info:nn {#1} { #2 ~=~ #3 } + \keys_set:nn { siunitx } { #2 = #3 } + } } \cs_generate_variant:Nn \@@_option_deprecated:nnn { nnV } % \end{macrocode} @@ -699,18 +698,6 @@ } , literal-superscript-as-power .code:n = { \@@_option_removed:V \l_keys_key_tl } , - per-mode / reciprocal .code:n = - { - \@@_option_deprecated:nn - { per-mode~=~reciprocal } - { per-mode~=~power } - } , - per-mode / reciprocal-positive-first .code:n = - { - \@@_option_deprecated:nn - { per-mode~=~reciprocal-positive-first } - { per-mode~=~power-positive-first } - } , power-font .code:n = { \@@_option_removed:V \l_keys_key_tl } , qualifier-mode / brackets .code:n = @@ -737,6 +724,38 @@ } % \end{macrocode} % +% The deprecated settings for |per-mode| have to be handled manually as +% |per-mode| is no longer a choice. +% \begin{macrocode} +\keys_define:nn { siunitx } + { + display-per-mode / reciprocal .code:n = + { + \@@_option_deprecated:nn + { per-mode~=~reciprocal } + { per-mode~=~power } + } , + inline-per-mode / reciprocal .code:n = + { + \@@_option_deprecated:nn + { per-mode~=~reciprocal } + { per-mode~=~power } + } , + display-per-mode / reciprocal-positive-first .code:n = + { + \@@_option_deprecated:nn + { per-mode~=~reciprocal-positive-first } + { per-mode~=~power-positive-first } + } , + inline-per-mode / reciprocal-positive-first .code:n = + { + \@@_option_deprecated:nn + { per-mode~=~reciprocal-positive-first } + { per-mode~=~power-positive-first } + } + } +% \end{macrocode} +% % \subsection{Quantity units} % % \begin{macrocode} @@ -856,10 +875,11 @@ % \begin{macro}{\si} % A straight copy of \cs{unit}. % \begin{macrocode} -\NewDocumentCommand \si { O { } m } +\NewDocumentCommand \si { O { } > { \TrimSpaces } m } { \mode_leave_vertical: \group_begin: + \siunitx_unit_options_apply:n {#2} \keys_set:nn { siunitx } {#1} \siunitx_unit_format:nN {#2} \l_@@_tmp_tl \siunitx_print_unit:V \l_@@_tmp_tl @@ -871,10 +891,11 @@ % \begin{macro}{\SI} % Almost the same as \cs{qty}, but with the addition pre-unit. % \begin{macrocode} -\NewDocumentCommand \SI { O { } m o m } +\NewDocumentCommand \SI { O { } m o > { \TrimSpaces } m } { \mode_leave_vertical: \group_begin: + \siunitx_unit_options_apply:n {#4} \keys_set:nn { siunitx } {#1} \IfNoValueF {#3} { diff --git a/Master/texmf-dist/source/latex/siunitx/siunitx-locale.dtx b/Master/texmf-dist/source/latex/siunitx/siunitx-locale.dtx index 36c83e034f6..cbf3ec14a0d 100644 --- a/Master/texmf-dist/source/latex/siunitx/siunitx-locale.dtx +++ b/Master/texmf-dist/source/latex/siunitx/siunitx-locale.dtx @@ -142,21 +142,24 @@ % % \subsection{Localisation} % -% Localisation makes use of the \pkg{translator} package. This only happens +% Localisation makes use of the \pkg{translations} package. This only happens % if it is available, and is transparent to the user. % \begin{macrocode} \file_if_exist:nT { translations.sty } { \RequirePackage { translations } - \DeclareTranslation { Catalan } { and } { i } - \DeclareTranslation { Slovene } { and } { in } - \DeclareTranslation { Catalan } { to~(numerical~range) } { a } - \DeclareTranslation { English } { to~(numerical~range) } { to } - \DeclareTranslation { French } { to~(numerical~range) } { Ã } - \DeclareTranslation { German } { to~(numerical~range) } { bis } - \DeclareTranslation { Polish } { to~(numerical~range) } { do } - \DeclareTranslation { Slovene } { to~(numerical~range) } { do } - \DeclareTranslation { Spanish } { to~(numerical~range) } { a } + \DeclareTranslation { Catalan } { and } { i } + \DeclareTranslation { Slovene } { and } { in } + \DeclareTranslation { Portuguese } { and } { e } + \DeclareTranslation { Catalan } { to~(numerical~range) } { a } + \DeclareTranslation { English } { to~(numerical~range) } { to } + \DeclareTranslation { French } { to~(numerical~range) } { Ã } + \DeclareTranslation { German } { to~(numerical~range) } { bis } + \DeclareTranslation { Polish } { to~(numerical~range) } { do } + \DeclareTranslation { Slovene } { to~(numerical~range) } { do } + \DeclareTranslation { Spanish } { to~(numerical~range) } { a } + \DeclareTranslation { Brazilian } { to~(numerical~range) } { a } + \DeclareTranslation { Portuguese } { to~(numerical~range) } { a } \keys_set:nn { siunitx } { list-final-separator = diff --git a/Master/texmf-dist/source/latex/siunitx/siunitx-number.dtx b/Master/texmf-dist/source/latex/siunitx/siunitx-number.dtx index 4f3708e7065..f64fb851929 100644 --- a/Master/texmf-dist/source/latex/siunitx/siunitx-number.dtx +++ b/Master/texmf-dist/source/latex/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} % diff --git a/Master/texmf-dist/source/latex/siunitx/siunitx-print.dtx b/Master/texmf-dist/source/latex/siunitx/siunitx-print.dtx index cb63a0e325f..0a7348ee66a 100644 --- a/Master/texmf-dist/source/latex/siunitx/siunitx-print.dtx +++ b/Master/texmf-dist/source/latex/siunitx/siunitx-print.dtx @@ -241,6 +241,16 @@ % The mappings between text and math weight are set . The standard setting is |false|. % \end{function} % +% \begin{function}{text-subscript-command, text-superscript-command} +% \begin{syntax} +% |text-subscript-command| = \meta{cmd} +% |text-superscript-command| = \meta{cmd} +% \end{syntax} +% Sets the command used when printing material in sub- or superscript +% positions in text mode. The standard settings are \cs{textsubscript} +% and \cs{textsuperscript}, respectively. +% \end{function} +% % \begin{function}{unit-color} % \begin{syntax} % |unit-color| = \meta{color} @@ -345,6 +355,8 @@ % \l_@@_math_version_bool , % \l_@@_math_family_bool , % \l_@@_text_font_tl , +% \l_@@_text_sub_tl , +% \l_@@_text_super_tl , % \l_@@_math_series_bool % } % Options which apply to the main formatting routine, and so are not tied @@ -380,6 +392,10 @@ \l_@@_math_family_bool , text-font-command .tl_set:N = \l_@@_text_font_tl , + text-subscript-command .tl_set:N = + \l_@@_text_sub_tl , + text-superscript-command .tl_set:N = + \l_@@_text_super_tl , text-series-to-math .bool_set:N = \l_@@_math_series_bool , unit-color .tl_set:N = @@ -797,7 +813,7 @@ % \begin{macro}{\@@_text_replace:Nnnn} % \begin{macro}{\@@_text_replace_frac:n} % \begin{macro}{\@@_text_sub:n, \@@_text_super:n} -% \begin{macro}{\@@_text_scripts:NnN} +% \begin{macro}{\@@_text_scripts:nnN} % \begin{macro}{\@@_text_scripts:} % \begin{macro}{\@@_text_scripts_one:NnN} % \begin{macro}{\@@_text_scripts_two:NnNn} @@ -844,18 +860,29 @@ \tl_set:Nn \l_@@_tmp_tl {#1} \tl_if_empty:NF \l_@@_tmp_tl { - \tl_if_empty:NF \l_siunitx_unit_font_tl - { \exp_after:wN \cs_set_eq:NN \l_siunitx_unit_font_tl \use:n } - \cs_set:Npn \mathord ##1 - { \@@_text_replace_first:N ##1 } - \cs_set:Npn \pm { \: \exp_not:N \textpm \: } - \tl_map_inline:nn - { \mp \ge \le \gg \ll } - { \cs_set:Npn ##1 { \exp_not:N \ensuremath { \exp_not:N ##1 } } } - \cs_set:Npn \cdot { \: \exp_not:N \textperiodcentered \: } - \cs_set:Npn \times { \: \exp_not:N \texttimes \: } - \protected@edef \l_@@_tmp_tl - { \exp_after:wN \@@_text_replace_first:N \l_@@_tmp_tl } + \tl_if_empty:NF \l_siunitx_unit_font_tl + { \exp_after:wN \cs_set_eq:NN \l_siunitx_unit_font_tl \use:n } + \cs_set:Npn \mathord ##1 + { \@@_text_replace_first:N ##1 } + \group_begin: + \cs_set:Npn \pm { \: \exp_not:N \textpm \: } + \tl_map_inline:nn + { \mp \ge \le \gg \ll \angle } + { + \cs_set:Npn ##1 + { \exp_not:N \ensuremath { \exp_not:N ##1 } } + } + \cs_set:Npn \cdot { \: \exp_not:N \textperiodcentered \: } + \cs_set:Npn \sqrt ##1 + { + \exp_not:N \ensuremath + { \exp_not:N \sqrt { \exp_not:N \text {##1} } } + } + \cs_set:Npn \times { \: \exp_not:N \texttimes \: } + \protected@edef \l_@@_tmp_tl + { \exp_after:wN \@@_text_replace_first:N \l_@@_tmp_tl } + \exp_args:NNNV \group_end: + \tl_set:Nn \l_@@_tmp_tl \l_@@_tmp_tl \@@_text_replace:N \l_@@_tmp_tl \@@_text_replace_aux:n { \tl_use:N \l_@@_tmp_tl } } @@ -935,15 +962,15 @@ % \begin{macrocode} \cs_new_protected:Npn \@@_text_sub:n #1 { - \@@_text_scripts:NnN - \textsubscript {#1} \@@_text_super:n + \@@_text_scripts:VnN + \l_@@_text_sub_tl {#1} \@@_text_super:n } \cs_new_protected:Npn \@@_text_super:n #1 { - \@@_text_scripts:NnN - \textsuperscript {#1} \@@_text_sub:n + \@@_text_scripts:VnN + \l_@@_text_super_tl {#1} \@@_text_sub:n } -\cs_new_protected:Npn \@@_text_scripts:NnN #1#2#3 +\cs_new_protected:Npn \@@_text_scripts:nnN #1#2#3 { \cs_set_protected:Npn \@@_text_scripts: { @@ -956,6 +983,7 @@ } \peek_after:Nw \@@_text_scripts: } +\cs_generate_variant:Nn \@@_text_scripts:nnN { V } \cs_new_protected:Npn \@@_text_scripts: { } % \end{macrocode} % In the simple case of one script item, we have to do a search-and-replace @@ -1039,20 +1067,22 @@ % \begin{macrocode} \keys_set:nn { siunitx } { - color = , - mode = math , - number-color = , - number-mode = math , - propagate-math-font = false , - reset-math-version = true , - reset-text-shape = true , - reset-text-series = true , - reset-text-family = true , - text-family-to-math = false , - text-font-command = , - text-series-to-math = false , - unit-color = , - unit-mode = math + color = , + mode = math , + number-color = , + number-mode = math , + propagate-math-font = false , + reset-math-version = true , + reset-text-shape = true , + reset-text-series = true , + reset-text-family = true , + text-family-to-math = false , + text-font-command = , + text-subscript-command = \textsubscript , + text-superscript-command = \textsuperscript , + text-series-to-math = false , + unit-color = , + unit-mode = math } % \end{macrocode} % diff --git a/Master/texmf-dist/source/latex/siunitx/siunitx-quantity.dtx b/Master/texmf-dist/source/latex/siunitx/siunitx-quantity.dtx index e4dc93200e7..4c311d5d081 100644 --- a/Master/texmf-dist/source/latex/siunitx/siunitx-quantity.dtx +++ b/Master/texmf-dist/source/latex/siunitx/siunitx-quantity.dtx @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% File: siunitx-quantity.dtx Copyright (C) 2018-2021 Joseph Wright +% File: siunitx-quantity.dtx Copyright (C) 2018-2022 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 @@ -151,7 +151,7 @@ % \begin{variable}{\l_@@_tmp_fp, \l_@@_tmp_tl} % Scratch space. % \begin{macrocode} -\tl_new:N \l_@@_tmp_fp +\fp_new:N \l_@@_tmp_fp \tl_new:N \l_@@_tmp_tl % \end{macrocode} % \end{variable} diff --git a/Master/texmf-dist/source/latex/siunitx/siunitx-unit.dtx b/Master/texmf-dist/source/latex/siunitx/siunitx-unit.dtx index cc3b5a2b41c..7147db42757 100644 --- a/Master/texmf-dist/source/latex/siunitx/siunitx-unit.dtx +++ b/Master/texmf-dist/source/latex/siunitx/siunitx-unit.dtx @@ -33,7 +33,7 @@ \textsc { \exp_args:NV \tl_if_head_eq_charcode:nNTF \f@series { m } - { \tl_lower_case:n } + { \text_lowercase:n } { \use:n } {#1} } @@ -74,7 +74,7 @@ % \begin{documentation} % % This submodule is dedicated to formatting physical units. The main function, -% \cs{siunitx_unit_format:nN}, takes user input specify physical units and +% \cs{siunitx_unit_format:nN}, takes user input specifying physical units and % converts it into a formatted token list suitable for typesetting in math % mode. While the formatter will deal correctly with \enquote{literal} user % input, the key strength of the module is providing a method to describe @@ -84,15 +84,15 @@ % % A small number of \LaTeXe{} math mode commands are assumed to be available % as part of the formatted output. The \cs{mathchoice} command -% (normally the \TeX{} primitive) is needed when using -% |per-mode = symbol-or-fraction|. The commands \cs{frac}, \cs{mathrm}, +% (normally the \TeX{} primitive) is needed when using different settings +% for inline and siplay |per-mode|. The commands \cs{frac}, \cs{mathrm}, % \cs{mbox}, \verb*|\ | and \cs{,} are used by the standard module settings. % For the display of colored (highlighted) and cancelled units, the commands % \cs{textcolor} and \cs{cancel} are assumed to be available. % % \section{Formatting units} % -% \begin{function}{\siunitx_unit_format:nN, \siunitx_unit_format:xN} +% \begin{function}{\siunitx_unit_format:nN} % \begin{syntax} % \cs{siunitx_unit_format:nN} \Arg{units} \meta{tl~var} % \end{syntax} @@ -552,8 +552,7 @@ % \end{syntax} % Switch to determine whether brackets are added to the denominator part of % a unit when printed using inline fractional form (with |per-mode| as -% |repeated-symbol|, |symbol| or |symbol-or-fraction|). The standard setting -% is |true|. +% |repeated-symbol| or |symbol|). The standard setting is |true|. % \end{function} % % \begin{function}{extract-mass-in-kilograms} @@ -596,14 +595,14 @@ % mode is used directly. The standard setting is |true|. % \end{function} % -% \begin{function}{per-mode} +% \begin{function}{per-mode, inline-per-mode, display-per-mode} % \begin{syntax} -% |per-mode| = |fraction|\verb"|"|power|\verb"|"|power-positive-first|\verb"|"|repeated-symbol|\verb"|"|symbol|\verb"|"|symbol-or-fraction| +% |per-mode| = |fraction|\verb"|"|power|\verb"|"|power-positive-first|\verb"|"|repeated-symbol|\verb"|"|single-symbol|\verb"|"|symbol| % \end{syntax} % Selects how the negative powers (\cs{per}) are formatted: a choice from % the options |fraction|, |power|, |power-positive-first|, |repeated-symbol|, -% |symbol| and |symbol-or-fraction|. The option |fraction| generates -% fractional output when appropriate using the command specified by +% |single-symbol| and |symbol|. The option |fraction| +% generates fractional output when appropriate using the command specified by % the |fraction-command| option. The setting |power| uses reciprocal powers % leaving the units in the order of input, while |power-positive-first| uses % the same display format but sorts units such that the positive powers @@ -611,9 +610,14 @@ % by |per-symbol|) between positive and negative powers, while % |repeated-symbol| uses the same symbol but places it before \emph{every} % unit with a negative power (this is mathematically \enquote{wrong} but -% often seen in real work). Finally, |symbol-or-fraction| acts like -% |symbol| for inline output and like |fraction| when the output is used -% in a display math environment. The standard setting is |power|. +% often seen in real work). The option |single-symbol| will use a symbol if +% exactly one is required (\foreign{i.e.}~with a single negative power), and +% will otherwise use powers. The standard setting is |power|. +% +% The |inline-...| and |display-...| settings take the same options and work +% in exactly the same way, but are restricted in where they apply. The +% |display| version only applies in display math contexts, and the |inline| +% version applies in all others. % \end{function} % % \begin{function}{per-symbol} @@ -621,8 +625,25 @@ % |per-symbol| = \meta{symbol} % \end{syntax} % Specifies the symbol to be used to denote negative powers when the option -% |per-mode| is set to |repeated-symbol|, |symbol| or |symbol-or-fraction|. -% The standard setting is |/|. +% |per-mode| is set to |repeated-symbol| or |symbol|. The standard setting +% is |/|. +% \end{function} +% +% \begin{function}{per-symbol-script-correction} +% \begin{syntax} +% |per-symbol-script-correction| = \meta{insert} +% \end{syntax} +% Specifies the tokens used to correct spacing when the symbol set by +% |per-symbol| is immediately preceded by a superscript power. The +% standard setting is |\!|. +% \end{function} +% +% \begin{function}{power-half-as-sqrt} +% \begin{syntax} +% |power-half-as-sqrt| = |true|\verb"|"|false| +% \end{syntax} +% Used to determine whether a power of exactly half is converted to +% \cs{sqrt} in the output. The standard setting is |false| % \end{function} % % \begin{function}{qualifier-mode} @@ -692,11 +713,13 @@ \cs_generate_variant:Nn \tl_replace_all:Nnn { NnV } % \end{macrocode} % +% \begin{variable}{\l_@@_tmp_bool} % \begin{variable}{\l_@@_tmp_fp} % \begin{variable}{\l_@@_tmp_int} % \begin{variable}{\l_@@_tmp_tl} % Scratch space. % \begin{macrocode} +\bool_new:N \l_@@_tmp_bool \fp_new:N \l_@@_tmp_fp \int_new:N \l_@@_tmp_int \tl_new:N \l_@@_tmp_tl @@ -704,6 +727,7 @@ % \end{variable} % \end{variable} % \end{variable} +% \end{variable} % % \begin{variable}{\c_@@_math_subscript_tl} % Useful tokens with awkward category codes. @@ -1120,7 +1144,7 @@ } { \bool_if:NTF \l_@@_forbid_literal_bool - { \msg_error:nnn { siunitx } { unit / literal } {#1} } + { \msg_error:nnn { siunitx } { literal-unit } {#1} } { \@@_format_literal:n {#1} } } } @@ -1482,7 +1506,7 @@ \prop_if_in:NVTF \l_@@_parsed_prop \l_@@_tmp_tl { - \msg_error:nnxx { siunitx } { unit / duplicate-part } + \msg_error:nnxx { siunitx } { duplicate-part } { \exp_not:n {#1} } { \token_to_str:N #3 } } { @@ -1530,7 +1554,7 @@ } { \msg_error:nnxx { siunitx } - { unit / part-before-unit } { power } { \token_to_str:N #1 } + { part-before-unit } { power } { \token_to_str:N #1 } } } \cs_new_protected:Npn \@@_parse_qualifier:nn #1#2 @@ -1544,7 +1568,7 @@ } { \msg_error:nnnn { siunitx } - { unit / part-before-unit } { qualifier } { \token_to_str:N #1 } + { part-before-unit } { qualifier } { \token_to_str:N #1 } } } % \end{macrocode} @@ -1606,7 +1630,7 @@ { \bool_set_true:N \l_@@_per_bool \cs_set_protected:Npn \per - { \msg_error:nn { siunitx } { unit / duplicate-sticky-per } } + { \msg_error:nn { siunitx } { duplicate-sticky-per } } } { \@@_parse_add:nnnn @@ -1670,7 +1694,7 @@ \tl_set:Nx \l_@@_tmp_tl { ##1 - \int_eval:n { \l_@@_position_int + 1 } } \prop_if_in:NVT \l_@@_parsed_prop \l_@@_tmp_tl - { \msg_error:nnn { siunitx } { unit / dangling-part } { ##1 } } + { \msg_error:nnn { siunitx } { dangling-part } { ##1 } } } } % \end{macrocode} @@ -1685,6 +1709,8 @@ % \l_@@_forbid_literal_bool , % \l_@@_parse_bool , % \l_@@_per_symbol_tl , +% \l_@@_per_script_tl , +% \l_@@_half_sqrt_bool , % \l_@@_qualifier_mode_tl , % \l_@@_qualifier_phrase_tl % } @@ -1694,57 +1720,40 @@ { bracket-unit-denominator .bool_set:N = \l_@@_denominator_bracket_bool , + display-per-mode .choices:nn = + { + fraction , + power , + power-positive-first , + repeated-symbol , + symbol , + single-symbol + } + { \str_set:Nn \l_@@_per_display_str {#1} } , forbid-literal-units .bool_set:N = \l_@@_forbid_literal_bool , fraction-command .tl_set:N = \l_siunitx_unit_fraction_tl , parse-units .bool_set:N = \l_@@_parse_bool , - per-mode .choice: , - per-mode / fraction .code:n = + inline-per-mode .choices:nn = { - \bool_set_false:N \l_@@_autofrac_bool - \bool_set_false:N \l_@@_per_symbol_bool - \bool_set_true:N \l_@@_powers_positive_bool - \bool_set_true:N \l_@@_two_part_bool - } , - per-mode / power .code:n = - { - \bool_set_false:N \l_@@_autofrac_bool - \bool_set_false:N \l_@@_per_symbol_bool - \bool_set_false:N \l_@@_powers_positive_bool - \bool_set_false:N \l_@@_two_part_bool - } , - per-mode / power-positive-first .code:n = - { - \bool_set_false:N \l_@@_autofrac_bool - \bool_set_false:N \l_@@_per_symbol_bool - \bool_set_false:N \l_@@_powers_positive_bool - \bool_set_true:N \l_@@_two_part_bool - } , - per-mode / repeated-symbol .code:n = - { - \bool_set_false:N \l_@@_autofrac_bool - \bool_set_true:N \l_@@_per_symbol_bool - \bool_set_true:N \l_@@_powers_positive_bool - \bool_set_false:N \l_@@_two_part_bool - } , - per-mode / symbol .code:n = - { - \bool_set_false:N \l_@@_autofrac_bool - \bool_set_true:N \l_@@_per_symbol_bool - \bool_set_true:N \l_@@_powers_positive_bool - \bool_set_true:N \l_@@_two_part_bool - } , - per-mode / symbol-or-fraction .code:n = - { - \bool_set_true:N \l_@@_autofrac_bool - \bool_set_true:N \l_@@_per_symbol_bool - \bool_set_true:N \l_@@_powers_positive_bool - \bool_set_true:N \l_@@_two_part_bool - } , + fraction , + power , + power-positive-first , + repeated-symbol , + symbol , + single-symbol + } + { \str_set:Nn \l_@@_per_inline_str {#1} } , + per-mode .meta:n = + { display-per-mode = {#1} , inline-per-mode = {#1} } , per-symbol .tl_set:N = \l_@@_per_symbol_tl , + per-symbol-script-correction .tl_set:N = + \l_@@_per_script_tl , + power-half-as-sqrt .bool_set:N = + \l_@@_half_sqrt_bool , qualifier-mode .choices:nn = { bracket , combine , phrase , subscript } { \tl_set_eq:NN \l_@@_qualifier_mode_tl \l_keys_choice_tl } , @@ -1779,9 +1788,16 @@ % \end{macrocode} % \end{variable} % +% \begin{variable}{\l_@@_per_display_str, \l_@@_per_inline_str} +% The data storage for |per-mode| settings. +% \begin{macrocode} +\str_new:N \l_@@_per_display_str +\str_new:N \l_@@_per_inline_str +% \end{macrocode} +% \end{variable} +% % \begin{variable} % { -% \l_@@_autofrac_bool , % \l_@@_powers_positive_bool , % \l_@@_per_symbol_bool , % \l_@@_two_part_bool @@ -1789,7 +1805,6 @@ % Dealing with the various ways that reciprocal (\cs{per}) can be handled % requires a few different switches. % \begin{macrocode} -\bool_new:N \l_@@_autofrac_bool \bool_new:N \l_@@_per_symbol_bool \bool_new:N \l_@@_powers_positive_bool \bool_new:N \l_@@_two_part_bool @@ -1844,6 +1859,17 @@ % \end{macrocode} % \end{variable} % +% \begin{variable}{\l_@@_current_script_bool, \l_@@_script_bool} +% A pair of flags to track whether the last entry in the numerator has a +% superscript. This is tracked to deal with spacing immediately before +% a slash (symbol), if required. Two flags are needed as otherwise the +% denominator interferes. +% \begin{macrocode} +\bool_new:N \l_@@_current_script_bool +\bool_new:N \l_@@_script_bool +% \end{macrocode} +% \end{variable} +% % \begin{variable}{\l_@@_current_tl, \l_@@_part_tl} % Building up the (partial) formatted unit requires some token list storage. % Each part of the unit combination that is recovered also has to be @@ -1873,14 +1899,42 @@ % \end{variable} % % \begin{macro}{\@@_format_parsed:} -% \begin{macro}{\@@_format_parsed_aux:n} +% \begin{macro} +% {\@@_format_parsed:n, \@@_format_parsed:V, \@@_format_parsed_aux:n} % The main formatting routine is essentially a loop over each position, % reading the various parts of the unit to build up complete unit -% combination. +% combination. When the two types of output need to be different, the +% formatter has to be run twice. % \begin{macrocode} \cs_new_protected:Npn \@@_format_parsed: { + \str_if_eq:NNTF + \l_@@_per_inline_str + \l_@@_per_display_str + { \@@_format_parsed:V \l_@@_per_inline_str } + { + \group_begin: + \@@_format_parsed:V \l_@@_per_inline_str + \exp_args:NNNV \group_end: + \tl_set:Nn \l_@@_tmp_tl \l_@@_formatted_tl + \group_begin: + \@@_format_parsed:V \l_@@_per_display_str + \exp_args:NNNV \group_end: + \tl_set:Nn \l_@@_formatted_tl \l_@@_formatted_tl + \tl_set:Nx \l_@@_formatted_tl + { + \mathchoice + { \exp_not:V \l_@@_formatted_tl } + { \exp_not:V \l_@@_tmp_tl } + { \exp_not:V \l_@@_tmp_tl } + { \exp_not:V \l_@@_tmp_tl } + } + } + } +\cs_new_protected:Npn \@@_format_parsed:n #1 + { \int_set_eq:NN \l_@@_total_int \l_@@_position_int + \use:c { @@_format_init_ #1 : } \tl_clear:N \l_@@_denominator_tl \tl_clear:N \l_@@_formatted_tl \fp_zero:N \l_@@_prefix_fp @@ -1897,6 +1951,7 @@ \l_@@_position_int < \l_@@_total_int { \bool_set_false:N \l_@@_bracket_bool + \bool_set_false:N \l_@@_current_script_bool \tl_clear:N \l_@@_current_tl \bool_set_false:N \l_@@_font_bool \bool_set_true:N \l_@@_numerator_bool @@ -1907,6 +1962,7 @@ } \@@_format_finalise: } +\cs_generate_variant:Nn \@@_format_parsed:n { V } \cs_new_protected:Npn \@@_format_parsed_aux:n #1 { \tl_set:Nx \l_@@_tmp_tl @@ -1919,6 +1975,55 @@ % \end{macro} % \end{macro} % +% \begin{macro} +% { +% \@@_format_init_fracton: , +% \@@_format_init_power: , +% \@@_format_init_power-positive-first: , +% \@@_format_init_repeated-symbol: , +% \@@_format_init_symbol: , +% \@@_format_init_single-symbol: , +% } +% To set up the various versions of |per-mode|. +% \begin{macrocode} +\cs_new_protected:Npn \@@_format_init_fraction: + { + \bool_set_false:N \l_@@_per_symbol_bool + \bool_set_true:N \l_@@_powers_positive_bool + \bool_set_true:N \l_@@_two_part_bool + } +\cs_new_protected:Npn \@@_format_init_power: + { + \bool_set_false:N \l_@@_per_symbol_bool + \bool_set_false:N \l_@@_powers_positive_bool + \bool_set_false:N \l_@@_two_part_bool + } +\cs_new_protected:cpn { @@_format_init_power-positive-first: } + { + \bool_set_false:N \l_@@_per_symbol_bool + \bool_set_false:N \l_@@_powers_positive_bool + \bool_set_true:N \l_@@_two_part_bool + } +\cs_new_protected:cpn { @@_format_init_repeated-symbol: } + { + \bool_set_true:N \l_@@_per_symbol_bool + \bool_set_true:N \l_@@_powers_positive_bool + \bool_set_false:N \l_@@_two_part_bool + } +\cs_new_protected:Npn \@@_format_init_symbol: + { + \bool_set_true:N \l_@@_per_symbol_bool + \bool_set_true:N \l_@@_powers_positive_bool + \bool_set_true:N \l_@@_two_part_bool + } +\cs_new_protected:cpn { @@_format_init_single-symbol: } + { + \@@_format_init_power: + \@@_format_symbol_or_power: + } +% \end{macrocode} +% \end{macro} +% % \begin{macro}{\@@_format_combine_exp:} % To combine an exponent into the first prefix, we first adjust for any % power, then deal with any existing prefix, before looking up the @@ -1936,7 +2041,7 @@ \l_@@_tmp_tl \l_@@_tmp_tl { \prop_get:NnN \l_@@_parsed_prop { prefix-1 } \l_@@_tmp_tl - \msg_error:nnx { siunitx } { unit / non-numeric-exponent } + \msg_error:nnx { siunitx } { non-numeric-exponent } { \l_@@_tmp_tl } \tl_set:Nn \l_@@_tmp_tl { 0 } } @@ -1951,7 +2056,7 @@ \l_@@_tmp_tl \l_@@_tmp_tl { \prop_put:NnV \l_@@_parsed_prop { prefix-1 } \l_@@_tmp_tl } { - \msg_error:nnx { siunitx } { unit / non-convertible-exponent } + \msg_error:nnx { siunitx } { non-convertible-exponent } { \l_@@_tmp_tl } } } @@ -2015,6 +2120,36 @@ % \end{macrocode} % \end{macro} % +% \begin{macro}{\@@_format_symbol_or_power:} +% Check if there is exactly one negative power align with at least one +% positive one. Assuming there is, flip from (effectively) |power| to +% |symbol|. +% \begin{macrocode} +\cs_new_protected:Npn \@@_format_symbol_or_power: + { + \int_compare:nNnT \l_@@_total_int > 1 + { + \bool_set_false:N \l_@@_tmp_bool + \int_step_inline:nn \l_@@_total_int + { + \prop_get:NnNT \l_@@_parsed_prop { power- ##1 } + \l_@@_tmp_tl + { + \int_compare:nNnT \l_@@_tmp_tl < 0 + { + \bool_if:NTF \l_@@_tmp_bool + { \bool_set_false:N \l_@@_tmp_bool } + { \bool_set_true:N \l_@@_tmp_bool } + } + } + } + \bool_if:NT \l_@@_tmp_bool + { \@@_format_init_symbol: } + } + } +% \end{macrocode} +% \end{macro} +% % \begin{macro}[EXP]{\@@_format_bracket:N} % A quick utility function which wraps up a token list variable in brackets % if they are required. @@ -2033,7 +2168,7 @@ % \end{macro} % % \begin{macro}{\@@_format_power:} -% \begin{macro}[EXP]{\@@_format_power_aux:wTF} +% \begin{macro}[EXP]{\@@_format_power_aux:w} % \begin{macro} % { % \@@_format_power_positive: , @@ -2049,16 +2184,17 @@ \cs_new_protected:Npn \@@_format_power: { \@@_format_font: - \exp_after:wN \@@_format_power_aux:wTF + \exp_after:wN \@@_format_power_aux:w \l_@@_part_tl - \q_stop { \@@_format_power_negative: } { \@@_format_power_positive: } } -\cs_new:Npn \@@_format_power_aux:wTF #1 - #2 \q_stop +\cs_new:Npn \@@_format_power_aux:w #1 - #2 \q_stop { \tl_if_empty:nTF {#1} } % \end{macrocode} % In the case of positive powers, there is little to do: add the power -% as a subscript (must be required as the parser ensures it's $\neq 1$). +% as a superscript (the parser ensures that this is $\neq 1$, so we do not +% need a test here). % \begin{macrocode} \cs_new_protected:Npn \@@_format_power_positive: { \@@_format_power_superscript: } @@ -2088,14 +2224,24 @@ { \exp_not:n {#1} } % \end{macrocode} % Adding the power as a superscript has the slight complication that there -% is the possibility of needing some brackets. The superscript itself uses -% \cs{sp} as that avoids any category code issues and also allows redirection -% at a higher level more readily. +% is the possibility of needing some brackets. % \begin{macrocode} \cs_new_protected:Npn \@@_format_power_superscript: { - \exp_after:wN \@@_format_power_superscipt:w - \l_@@_part_tl . . \q_stop + \bool_lazy_and:nnTF + { \l_@@_half_sqrt_bool } + { \str_if_eq_p:Vn \l_@@_part_tl { 0.5 } } + { + \tl_set:Nx \l_@@_current_tl + { + \exp_not:N \sqrt + { \exp_not:V \l_@@_current_tl } + } + } + { + \exp_after:wN \@@_format_power_superscipt:w + \l_@@_part_tl . . \q_stop + } } \cs_new_protected:Npn \@@_format_power_superscipt:w #1 . #2 . #3 \q_stop { @@ -2123,8 +2269,9 @@ { \@@_format_bracket:N \l_@@_current_tl ^ { \siunitx_number_output:N \l_@@_tmp_tl } - } + } } + \bool_set_true:N \l_@@_current_script_bool \bool_set_false:N \l_@@_bracket_bool } % \end{macrocode} @@ -2210,6 +2357,7 @@ % \begin{macrocode} \cs_new_protected:Npn \@@_format_qualifier: { + \bool_set_false:N \l_@@_current_script_bool \use:c { @@_format_qualifier_ @@ -2318,6 +2466,8 @@ } \cs_new_protected:Npn \@@_format_output_aux: { + \bool_set_eq:NN \l_@@_script_bool + \l_@@_current_script_bool \@@_format_output_aux:nV { formatted } \l_@@_product_tl } @@ -2427,36 +2577,9 @@ { \tl_if_empty:NT \l_@@_formatted_tl { \tl_set:Nn \l_@@_formatted_tl { 1 } } - \bool_if:NTF \l_@@_autofrac_bool - { \@@_format_finalise_autofrac: } - { - \bool_if:NTF \l_@@_per_symbol_bool - { \@@_format_finalise_symbol: } - { \@@_format_finalise_fraction: } - } - } -% \end{macrocode} -% For the \enquote{auto-selected} fraction method, the two other auxiliary -% functions are used to do both forms of formatting. So that everything -% required is available, this needs one group so that the second auxiliary -% receives the correct input. After that it is just a case of applying -% \cs{mathchoice} to the formatted output. -% \begin{macrocode} -\cs_new_protected:Npn \@@_format_finalise_autofrac: - { - \group_begin: - \@@_format_finalise_fraction: - \exp_args:NNNV \group_end: - \tl_set:Nn \l_@@_tmp_tl \l_@@_formatted_tl - \@@_format_finalise_symbol: - \tl_set:Nx \l_@@_formatted_tl - { - \mathchoice - { \exp_not:V \l_@@_tmp_tl } - { \exp_not:V \l_@@_formatted_tl } - { \exp_not:V \l_@@_formatted_tl } - { \exp_not:V \l_@@_formatted_tl } - } + \bool_if:NTF \l_@@_per_symbol_bool + { \@@_format_finalise_symbol: } + { \@@_format_finalise_fraction: } } % \end{macrocode} % When using a fraction function the two parts are now assembled. @@ -2470,11 +2593,17 @@ { \exp_not:V \l_@@_denominator_tl } } } +% \end{macrocode} +% Add the correction if required: no \cs{relax} needed as we know there is a +% non-expandable token following. +% \begin{macrocode} \cs_new_protected:Npn \@@_format_finalise_symbol: { \tl_set:Nx \l_@@_formatted_tl { \exp_not:V \l_@@_formatted_tl + \bool_if:NT \l_@@_script_bool + { \exp_not:V \l_@@_per_script_tl } \exp_not:V \l_@@_per_symbol_tl \@@_format_bracket:N \l_@@_denominator_tl } @@ -2761,43 +2890,43 @@ % \subsection{Messages} % % \begin{macrocode} -\msg_new:nnnn { siunitx } { unit / dangling-part } +\msg_new:nnnn { siunitx } { dangling-part } { Found~#1~part~with~no~unit. } { Each~#1~part~must~be~associated~with~a~unit:~a~#1~part~was~found~ but~no~following~unit~was~given. } -\msg_new:nnnn { siunitx } { unit / duplicate-part } +\msg_new:nnnn { siunitx } { duplicate-part } { Duplicate~#1~part:~#2. } { Each~unit~may~have~only~one~#1:\\ the~additional~#1~part~'#2'~will~be~ignored. } -\msg_new:nnnn { siunitx } { unit / duplicate-sticky-per } +\msg_new:nnnn { siunitx } { duplicate-sticky-per } { Duplicate~\token_to_str:N \per. } { When~the~'sticky-per'~option~is~active,~only~one~ \token_to_str:N \per \ may~appear~in~a~unit. } -\msg_new:nnnn { siunitx } { unit / literal } +\msg_new:nnnn { siunitx } { literal-unit } { Literal~units~disabled. } { You~gave~the~literal~input~'#1'~ but~literal~unit~output~is~disabled. } -\msg_new:nnnn { siunitx } { unit / non-convertible-exponent } +\msg_new:nnnn { siunitx } { non-convertible-exponent } { Exponent~'#1'~cannot~be~converted~into~a~symbolic~prefix. } { The~exponent~'#1'~does~not~match~with~any~of~the~symbolic~prefixes~ set~up. } -\msg_new:nnnn { siunitx } { unit / non-numeric-exponent } +\msg_new:nnnn { siunitx } { non-numeric-exponent } { Prefix~'#1'~does~not~have~a~numerical~value. } { The~prefix~'#1'~needs~to~be~combined~with~a~number,~but~it~has~no numerical~value. } -\msg_new:nnnn { siunitx } { unit / part-before-unit } +\msg_new:nnnn { siunitx } { part-before-unit } { Found~#1~part~before~first~unit:~#2. } { The~#1~part~'#2'~must~follow~after~a~unit:~ @@ -2805,6 +2934,31 @@ } % \end{macrocode} % +% \subsection{Deprecated options} +% +% To handle |per-mode = symbol-or-fraction|, there needs to be allowance for +% the fact that it is set up as a meta-option. That is done with appropriate +% code here for the two newer options. +% \begin{macrocode} +\keys_define:nn { siunitx } + { + display-per-mode / symbol-or-fraction .code:n = + { + \msg_info:nnnn { siunitx } { option-deprecated } + { per-mode~=~symbol-or-fraction } + { display-per-mode~=~fraction,~inline-per-mode~=~symbol } + \str_set:Nn \l_@@_per_display_str { fraction } + } , + inline-per-mode / symbol-or-fraction .code:n = + { + \msg_info:nnnn { siunitx } { option-deprecated } + { per-mode~=~symbol-or-fraction } + { display-per-mode~=~fraction,~inline-per-mode~=~symbol } + \str_set:Nn \l_@@_per_inline_str { symbol } + } + } +% \end{macrocode} +% % \subsection{Standard settings for module options} % % Some of these follow naturally from the point of definition @@ -2813,18 +2967,20 @@ % \begin{macrocode} \keys_set:nn { siunitx } { - bracket-unit-denominator = true , - forbid-literal-units = false , - fraction-command = \frac , - inter-unit-product = \, , - extract-mass-in-kilograms = true , - parse-units = true , - per-mode = power , - per-symbol = / , - qualifier-mode = subscript , - qualifier-phrase = , - sticky-per = false , - unit-font-command = \mathrm + bracket-unit-denominator = true , + forbid-literal-units = false , + fraction-command = \frac , + inter-unit-product = \, , + extract-mass-in-kilograms = true , + parse-units = true , + per-mode = power , + per-symbol = / , + per-symbol-script-correction = \! , + power-half-as-sqrt = false , + qualifier-mode = subscript , + qualifier-phrase = , + sticky-per = false , + unit-font-command = \mathrm } % \end{macrocode} % diff --git a/Master/texmf-dist/source/latex/siunitx/siunitx.dtx b/Master/texmf-dist/source/latex/siunitx/siunitx.dtx index d1de5e34da6..a5219ad957e 100644 --- a/Master/texmf-dist/source/latex/siunitx/siunitx.dtx +++ b/Master/texmf-dist/source/latex/siunitx/siunitx.dtx @@ -121,7 +121,7 @@ % % Identify the package and give the over all version information. % \begin{macrocode} -\ProvidesExplPackage {siunitx} {2022-04-04} {3.0.50} +\ProvidesExplPackage {siunitx} {2022-04-25} {3.1.0} {A comprehensive (SI) units package} % \end{macrocode} % @@ -144,11 +144,11 @@ { } } \clist_map_function:nN - { SIunits , sistyle , unitsdef , fancyunits } + { SIunits , sistyle , units , unitsdef , fancyunits } \@@_load_check:n \AtBeginDocument { - \clist_map_function:nN { SIunits , sistyle } + \clist_map_function:nN { SIunits , sistyle , units } \@@_load_check:n } % \end{macrocode} @@ -199,6 +199,35 @@ % % \subsection{Option handling} % +% Some messages. +% \begin{macrocode} +\msg_new:nnn { siunitx } { option-deprecated } + { + Option~"#1"~has~been~deprecated~in~this~release.\\ \\ + Use~"#2"~as~a~replacement. + } +% \end{macrocode} +% +% \begin{variable}{\g_@@_deprecated_seq} +% Used to avoid repeatedly warning about deprecated options: needed at the +% top level. +% \begin{macrocode} +\seq_new:N \g_@@_deprecated_seq +% \end{macrocode} +% \end{variable} +% +% \begin{macro}{\@@_deprecated_info:nn} +% To avoid repeated messages. +% \begin{macrocode} +\cs_new_protected:Npn \@@_deprecated_info:nn #1#2 + { + \seq_if_in:NnF \g_@@_deprecated_seq {#1} + { \msg_info:nnnn { siunitx } { option-deprecated } {#1} {#2} } + \seq_gput_right:Nn \g_@@_deprecated_seq {#1} + } +% \end{macrocode} +% \end{macro} +% % \begin{macrocode} \IfFormatAtLeastTF { 2022-06-01 } { \ProcessKeyOptions [ siunitx ] } @@ -266,16 +295,34 @@ % % \begin{macro}{\qty} % \begin{macrocode} -\@ifpackageloaded { physics } +\AtBeginDocument { - \msg_new:nnn { siunitx } { physics-pkg } + \@ifpackageloaded { physics } { - Detected~the~"physics"~package: \\ - Omitting~definition~of~\token_to_str:N \qty. + \msg_new:nnn { siunitx } { physics-pkg } + { + Detected~the~"physics"~package: \\ + omitting~definition~of~\token_to_str:N \qty. + \\ \\ + If~you~want~to~use~\qty with~the~siunitx~definition,~add~ + \\ \\ + \iow_indent:n + { + \token_to_str:N \AtBeginDocument + { + \token_to_str:N \RenewCommandCopy + \token_to_str:N \qty \token_to_str:N \SI + } + } + \\ \\ + to~your~preamble. + } + \msg_warning:nn { siunitx } { physics-pkg } } - \msg_warning:nn { siunitx } { physics-pkg } - \use_none:nnnn + { } } +\@ifpackageloaded { physics } + { \use_none:nnnn } { } \NewDocumentCommand \qty { O { } m > { \TrimSpaces } m } { @@ -310,17 +357,6 @@ \siunitx_print_number:V \l_@@_tmp_tl \group_end: } -\@ifpackageloaded { units } - { - \msg_new:nnn { siunitx } { units-pkg } - { - Detected~the~"units"~package: \\ - Omitting~definition~of~\token_to_str:N \unit. - } - \msg_warning:nn { siunitx } { units-pkg } - \use_none:nnnn - } - { } \NewDocumentCommand \unit { O { } > { \TrimSpaces } m } { \mode_leave_vertical: @@ -398,21 +434,29 @@ % \begin{macro}{\complexnum, \complexqty} % Interfaces for complex numbers. % \begin{macrocode} -\NewDocumentCommand \complexnum { O { } m } +\use:e + { + \NewDocumentCommand \exp_not:N \complexnum + { O { } > { \SplitArgument { 1 } { \c_colon_str } } m } + } { \mode_leave_vertical: \group_begin: \keys_set:nn { siunitx } {#1} - \siunitx_complex_number:n {#2} \l_@@_tmp_tl + \@@_complex_number_aux:nn #2 \group_end: } -\NewDocumentCommand \complexqty { O { } m m } +\use:e + { + \NewDocumentCommand \exp_not:N \complexqty + { O { } > { \SplitArgument { 1 } { \c_colon_str } } m m } + } { \mode_leave_vertical: \group_begin: \siunitx_unit_options_apply:n {#3} \keys_set:nn { siunitx } {#1} - \siunitx_complex_quantity:nn {#2} {#3} + \@@_complex_quantity_aux:nnn #2 {#3} \group_end: } % \end{macrocode} @@ -461,6 +505,26 @@ % \end{macrocode} % \end{macro} % +% \begin{macro}{\@@_complex_number_aux:nn} +% \begin{macro}{\@@_complex_quantity_aux:nnn} +% The same idea for complex values. +% \begin{macrocode} +\cs_new_protected:Npn \@@_complex_number_aux:nn #1#2 + { + \tl_if_novalue:nTF {#2} + { \siunitx_complex_number:n {#1} } + { \siunitx_complex_number:nn {#1} {#2} } + } +\cs_new_protected:Npn \@@_complex_quantity_aux:nnn #1#2#3 + { + \tl_if_novalue:nTF {#2} + { \siunitx_complex_quantity:nn {#1} {#3} } + { \siunitx_complex_quantity:nnn {#1} {#2} {#3} } + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% % \subsection{Table column} % % User interfaces in tabular constructs are provided using the mechanisms from diff --git a/Master/texmf-dist/source/latex/siunitx/siunitx.tex b/Master/texmf-dist/source/latex/siunitx/siunitx.tex index 8854ff3f75b..b10016c3b47 100644 --- a/Master/texmf-dist/source/latex/siunitx/siunitx.tex +++ b/Master/texmf-dist/source/latex/siunitx/siunitx.tex @@ -46,7 +46,7 @@ for those people who are interested. \textsc { \exp_args:NV \tl_if_head_eq_charcode:nNTF \f@series { m } - { \tl_lower_case:n } + { \text_lowercase:n } { \use:n } {#1} } @@ -79,7 +79,7 @@ for those people who are interested. } % For demos -\usepackage[french,german,polish,spanish,UKenglish]{babel} +\usepackage[portuguese,brazilian,catalan,french,german,polish,spanish,UKenglish]{babel} \AtBeginDocument{\shorthandoff{:<>}} \usepackage{translations} \usepackage{cancel} @@ -508,18 +508,20 @@ adjustment of the numerical values. \cs{complexnum}\oarg{options}\marg{number} \end{syntax} \end{function} -Typesets the complex number, which must be given in the form $a + b\mathrm{i}$ -or $a + \mathrm{i}b$. Processing of the numerical parts is otherwise identical -to the standard \cs{num} command. +Typesets the complex number, which can be given in the Cartesian form $a + +b\mathrm{i}$ or $a + \mathrm{i}b$, or in the polar form $r$\texttt{:}$\theta$. +Processing of the numerical parts is otherwise identical to the standard +\cs{num} command. \begin{function}{\complexqty} \begin{syntax} \cs{complexqty}\oarg{options}\marg{number}\marg{unit} \end{syntax} \end{function} -Typesets the complex quantity, which must be given in the form $a + b\mathrm{i}$ -or $a + \mathrm{i}b$. Processing of the numerical parts is otherwise identical -to the standard \cs{qty} command. +Typesets the complex number, which can be given in the Cartesian form $a + +b\mathrm{i}$ or $a + \mathrm{i}b$, or in the polar form $r$\texttt{:}$\theta$. +Processing of the numerical parts is otherwise identical to the standard +\cs{qty} command. \subsection{The unit macros} @@ -833,6 +835,7 @@ occur (for example with the standard \cs{pm} symbol). \midrule \DescribeUnit[watt]{W} \\ + \DescribeUnit[nanowatt]{nW} \\ \DescribeUnit[microwatt]{uW} \\ \DescribeUnit[milliwatt]{mW} \\ \DescribeUnit[kilowatt]{kW} \\ @@ -861,11 +864,21 @@ occur (for example with the standard \cs{pm} symbol). \midrule \DescribeUnit[henry]{H} \\ + \DescribeUnit[femtohenry]{fH} \\ + \DescribeUnit[picohenry]{pH} \\ + \DescribeUnit[nanohenry]{nH} \\ \DescribeUnit[millihenry]{mH} \\ \DescribeUnit[microhenry]{uH} \\ \midrule + \DescribeUnit[coulomb]{C} \\ + \DescribeUnit[nanocoulomb]{nC} \\ + \DescribeUnit[millicoulomb]{mC} \\ + \DescribeUnit[microcoulomb]{uC} \\ + + \midrule + \DescribeUnit[kelvin]{K} \\ \midrule @@ -1116,20 +1129,22 @@ Table~\ref{tab:opt:print}. Type & \multicolumn{1}{l@{}}{Default} \\ \midrule - color & Literal & \meta{none} \\ - mode & Choice & math \\ - number-color & Literal & \meta{none} \\ - number-mode & Choice & math \\ - propagate-math-font & Switch & false \\ - reset-math-version & Switch & true \\ - reset-text-family & Switch & true \\ - reset-text-series & Switch & true \\ - reset-text-shape & Switch & true \\ - text-family-to-math & Switch & false \\ - text-font-command & Literal & \meta{none} \\ - text-series-to-math & Switch & false \\ - unit-color & Literal & \meta{none} \\ - unit-mode & Choice & math \\ + color & Literal & \meta{none} \\ + mode & Choice & math \\ + number-color & Literal & \meta{none} \\ + number-mode & Choice & math \\ + propagate-math-font & Switch & false \\ + reset-math-version & Switch & true \\ + reset-text-family & Switch & true \\ + reset-text-series & Switch & true \\ + reset-text-shape & Switch & true \\ + text-family-to-math & Switch & false \\ + text-font-command & Literal & \meta{none} \\ + text-subscript-command & Literal & \cs{textsubscript} \\ + text-superscript-command & Literal & \cs{textsuperscript} \\ + text-series-to-math & Switch & false \\ + unit-color & Literal & \meta{none} \\ + unit-mode & Choice & math \\ \bottomrule \end{tabular} \end{table} @@ -1224,6 +1239,24 @@ font variant which does not feature them. \qty{123456789}{\kilo\volt\per\centi\metre} \end{LaTeXdemo} +\DescribeOption{text-subscript-command} +\DescribeOption{text-superscript-command} +In most cases, the commands \cs{textsubscript} and \cs{textsuperscript} are +appropriagte for creating sub- and superscript material in text mode. However, +when the \pkg{realscripts} package is loaded, it is possible that the output is +not as desired. These two commands are therefore available to allow tuning of +the results. They can also be used for non-standard effects, for example as +here adding color to subscripts. +\begin{LaTeXdemo} + \sisetup{unit-mode = text} + \unit{\kg\of{polymer}} \\ + \newcommand*\mysubscript[1]{% + \textsubscript{\textcolor{blue}{#1}}% + } + \sisetup{text-subscript-command = \mysubscript} + \unit{\kg\of{polymer}} +\end{LaTeXdemo} + \DescribeOption{color} \DescribeOption{number-color} \DescribeOption{unit-color} @@ -1272,6 +1305,7 @@ Table~\ref{tab:opt:num:in}. parse-numbers & Switch & true \\ retain-explicit-decimal-marker & Switch & false \\ retain-explicit-plus & Switch & false \\ + retain-negative-zero & Switch & false \\ retain-zero-uncertainty & Switch & false \\ \bottomrule \end{tabular} @@ -1331,6 +1365,12 @@ marker is seen in for example some \acro{NIST} publications.} \num{123.4(12)} \\ \num{123.4(1.2)} \end{LaTeXdemo} +Multiple uncertainties may also be given: these must all either be in the short +or the long form. +\begin{LaTeXdemo} + \num{123.4(12)(45)} \\ + \num{123.4 \pm 1.2 \pm 4.5} +\end{LaTeXdemo} \DescribeOption{parse-numbers} The \opt{parse-numbers} option turns the entire parsing system on and off. The @@ -1364,6 +1404,7 @@ most notably in that a decimal marker must be |.|. \DescribeOption{retain-explicit-decimal-marker} \DescribeOption{retain-explicit-plus} +\DescribeOption{retain-negative-zero} \DescribeOption{retain-zero-uncertainty} In some areas, a trailing decimal marker with no decimal part present is used to show that zeros in the integer part are significant. This can be enabled @@ -1372,13 +1413,16 @@ leading plus sign is usually unnecessary for positive numbers, and so they are not retained as-standard when parsing. The \opt{retain-explicit-plus} option is available to control this behaviour. Similarly, an uncertainty of zero is normally not meaningful, and so is ignored by the parser. This can be -controlled using the -\opt{retain-zero-uncertainty} option. +controlled using the \opt{retain-zero-uncertainty} option. Finally, a negative +sign for an entirely zero value may or may not have significance: this is +controlled by the \opt{retain-negative-zero} option. \begin{LaTeXdemo} \num{10.} \\ \num[retain-explicit-decimal-marker]{10.} \\ \num{+345} \\ \num[retain-explicit-plus]{+345} \\ + \num{-0} \\ + \num[retain-negative-zero]{-0} \\ \num{12.3(0)} \\ \num[retain-zero-uncertainty]{12.3(0)} \end{LaTeXdemo} @@ -1409,6 +1453,7 @@ way; the options are summarised in Table~\ref{tab:opt:num:post}. round-mode & Choice & none \\ round-pad & Switch & true \\ round-precision & Integer & 2 \\ + round-zero-positive & Switch & true \\ \bottomrule \end{tabular} \end{table} @@ -1542,6 +1587,18 @@ possible to obtain the value zero in these cases. \num{0.0045} \end{LaTeXdemo} +\DescribeOption{round-zero-positive} +When rounding negative numbers to a fixed number of places, a zero value may +result. Usually this is expressed as an unsigned value, but in some cases +retaining the negative sign may be desirable. This behaviour can be controlled +using the \opt{round-zero-positive} switch. +\begin{LaTeXdemo} + \sisetup{round-mode = places}% + \num{-0.001} \\ + \sisetup{round-zero-positive = false}% + \num{-0.001} +\end{LaTeXdemo} + \DescribeOption{drop-zero-decimal} It may be desirable to convert decimals to integers when the decimal part is zero. This is set up using the \opt{drop-zero-decimal} option, which applies @@ -1582,24 +1639,32 @@ conveys. The options are summarised in Table~\ref{tab:opt:num:out}. Type & \multicolumn{1}{l}{Default} \\ \midrule - bracket-negative-numbers & Switch & false \\ - exponent-base & Literal & 10 \\ - exponent-product & Math & \verb=\times= \\ - group-digits & Choice & all \\ - group-minimum-digits & integer & 5 \\ - group-separator & Literal & \cs{,} \\ - negative-color & Literal & \meta{none} \\ ^^A ( - output-close-uncertainty & Literal & ) \\ - output-decimal-marker & Literal & . \\ - output-exponent-marker & Literal & \meta{none} \\ - output-open-uncertainty & Literal & ( \\ ^^A ) - print-implicit-plus & Switch & false \\ - print-unity-mantissa & Switch & true \\ - print-zero-exponent & Switch & false \\ - print-zero-integer & Switch & false \\ - tight-spacing & Switch & false \\ - uncertainty-mode & Choice & compact \\ - uncertainty-separator & Literal & \meta{none} \\ + bracket-negative-numbers & Switch & false \\ + digit-group-size & Integer & 3 \\ + digit-group-first-size & Integer & 3 \\ + digit-group-other-size & Integer & 3 \\ + exponent-base & Literal & 10 \\ + exponent-product & Math & \verb=\times= \\ + group-digits & Choice & all \\ + group-minimum-digits & Integer & 5 \\ + group-separator & Literal & \cs{,} \\ + negative-color & Literal & \meta{none} \\ ^^A ( + output-close-uncertainty & Literal & ) \\ + output-decimal-marker & Literal & . \\ + output-exponent-marker & Literal & \meta{none} \\ + output-open-uncertainty & Literal & ( \\ ^^A ) + print-implicit-plus & Switch & false \\ + print-unity-mantissa & Switch & true \\ + print-zero-exponent & Switch & false \\ + print-zero-integer & Switch & false \\ + tight-spacing & Switch & false \\ + uncertainty-descriptor-mode & Choice & bracket-separator \\ + uncertainty-descriptor-separator & Literal & \cs{ } \\ + uncertainty-descriptors & Literal & \meta{none} \\ + uncertainty-mode & Choice & compact \\ + uncertainty-separator & Literal & \meta{none} \\ + zero-decimal-as-symbol & Switch & false \\ + zero-symbol & Literal & \verb=\mbox{---}= \\ \bottomrule \end{tabular} \end{table} @@ -1643,6 +1708,21 @@ separately for the integer and decimal parts of the number: grouping does not \num[group-minimum-digits = 5]{12345.67890} \end{LaTeXdemo} +\DescribeOption{digit-group-size} +\DescribeOption{digit-group-first-size} +\DescribeOption{digit-group-other-size} +The number of digits in each group can be controlled by the setting +\opt{digit-group-size}, which has standard value $3$. Finer control can be +achieved using \opt{digit-group-first-size} and \opt{digit-group-other-size}: +the first group is that immediately by the decimal point, the other value +applies to the second and subsequent groupings. These can be used for +example to achieve the grouping typically used in India (lakh). +\begin{LaTeXdemo} + \num{1234567890} \\ + \num[digit-group-size = 5]{1234567890} \\ + \num[digit-group-other-size = 2]{1234567890} +\end{LaTeXdemo} + \DescribeOption{output-decimal-marker} The decimal marker used in output is set using the \opt{output-decimal-marker} option; this can differ from the input marker. @@ -1672,9 +1752,9 @@ stored will be used in place of the normal product and base combination. \DescribeOption{output-open-uncertainty} \DescribeOption{output-close-uncertainty} \DescribeOption{uncertainty-separator} -When input is given including an uncertainty in a number, it can be printed -either with the uncertainty in brackets or as a separate number. This behaviour -is controlled by the \opt{uncertainty-mode} choice.When this is set to +When input is given including a single uncertainty, it can be printed either +with the uncertainty in brackets or as a separate number. This behaviour is +controlled by the \opt{uncertainty-mode} choice. When this is set to \opt{separate}, the uncertainty is printed as an entirely separate number preceded by \cs{pm}. Other settings all place the uncertainty in brackets directly attached to the main value. The standard setting of \opt{compact} @@ -1707,6 +1787,24 @@ respectively. Tokens may be inserted before the opening bracket using \num{1.234(5)} \end{LaTeXdemo} +\DescribeOption{uncertainty-descriptors} +\DescribeOption{uncertainty-descriptor-mode} +\DescribeOption{uncertainty-descriptor-separator} +Multiple uncertainties can be given for a number. These are always printed in a +separated form. When there is more than one uncertainty part, it may be useful +to describe the nature of this value. This can be achieved using the +\opt{uncertainty-descriptors} option, which take a comma-separated list of +descriptions. The formatting of the descriptors can be adjusted using the +settings \opt{uncertainty-descriptor-mode} and +\opt{uncertainty-descriptor-separator}. The choices for the \opt{mode} are +\opt{bracket}, \opt{bracket-separator}, \opt{separator} and \opt{subscript}. +\begin{LaTeXdemo} + \num{1.2(3)(4)} \\ + \sisetup{uncertainty-descriptors = {sys, stat}} + \num{1.2(3)(4)} \\ + \num[uncertainty-descriptor-mode = subscript]{1.2(3)(4)} +\end{LaTeXdemo} + \DescribeOption{bracket-ambiguous-numbers} There are certain combinations of numerical input which can be ambiguous. This can be corrected by adding brackets in the appropriate place, and is controlled @@ -1775,6 +1873,18 @@ printed (\foreign{i.e.}~\opt{print-zero-exponent} has a higher priority). \num[print-zero-integer = false]{0.123} \end{LaTeXdemo} +\DescribeOption{zero-decimal-as-symbol} +\DescribeOption{zero-symbol} +In some areas, particularly financial, entirely zero decimal parts are +replaced by a dash. This is supported by option \opt{zero-decimal-as-symbol}, +which then uses the material stored using \opt{zero-symbol} as the replacement. +\begin{LaTeXdemo} + \num{123.00} \\ + \sisetup{zero-decimal-as-symbol} + \num{123.00} \\ + \num[zero-symbol = \text{[{---}]}]{123.00} +\end{LaTeXdemo} + \subsection{Lists, products and ranges} Lists, products and ranges of numbers and quantities have a small number of @@ -1938,13 +2048,35 @@ numbers; these are summarised in Table~\ref{tab:opt:num:complex}. Type & \multicolumn{1}{l@{}}{Default} \\ \midrule + complex-angle-unit & Choice & degrees \\ + complex-mode & Choice & input \\ complex-root-position & Choice & after-number \\ + complex-symbol-angle & Literal & \cs{angle} \\ + complex-symbol-degree & Literal & \cs{degree} \\ input-complex-root & Literal & ij \\ output-complex-root & Literal & \verb=\mathrm{i}= \\ \bottomrule \end{tabular} \end{table} +\DescribeOption{complex-mode} +The format in which complex values are printed can be set using the +\opt{complex-mode} option. With the standard setting (\opt{input}), the complex +value is printed as-given. By setting the option to \opt{cartesian} or +\opt{polar}, the output format can be set to an Cartesian or polar form. +Conversion uses the \LaTeX3 floating-point unit, so is limited to $16$ decimal +places. When converting from Cartesian to polar form, the complex root symbol +must come at the \emph{end} of the imaginary part. It must also be specified +using \texttt{i}. +\begin{LaTeXdemo} + \complexnum{1 + i} \\ + \complexnum{1:45} \\ + \complexnum[complex-mode = cartesian]{1 + i} \\ + \complexnum[complex-mode = cartesian, round-mode = places]{1:45} \\ + \complexnum[complex-mode = polar]{1 + i} \\ + \complexnum[complex-mode = polar]{1:45} +\end{LaTeXdemo} + \DescribeOption{input-complex-root} When using complex numbers in input, the complex root $(\mathrm{i} = \sqrt{-1}\,)$ is indicated by one of the tokens stored in @@ -1974,6 +2106,21 @@ using the \opt{output-complex-root} setting. \complexnum[complex-root-position = after-number]{67-0.9i} \end{LaTeXdemo} +\DescribeOption{complex-angle-unit} +\DescribeOption{complex-symbol-angle} +\DescribeOption{complex-symbol-degree} +When printing or converting to polar form, the angle may be interpreted in +units set by \opt{complex-angle-unit}: one of \opt{degrees} or \opt{radians}. +The symbol used to denote the angle, and that used for units of degrees, +are controlled by the options \opt{complex-symbol-angle} and +\opt{complex-symbol-degree}, respectively. +\begin{LaTeXdemo} + \complexqty{1:1}{\ohm} \\ + \complexqty[complex-angle-unit = radians]{1:1}{\ohm} \\ + \complexqty[complex-symbol-angle = \mathrm{A}]{1:1}{\ohm} \\ + \complexqty[complex-symbol-degree = d]{1:1}{\ohm} +\end{LaTeXdemo} + \subsection{Angles} Angle processing provided by the \cs{ang} function has a set of options which @@ -2180,17 +2327,19 @@ the output directly (Table~\ref{tab:opt:units:out}). Type & \multicolumn{1}{l@{}}{Default} \\ \midrule - bracket-unit-denominator & Switch & true \\ - forbid-literal-units & Switch & false \\ - fraction-command & Literal & \cs{frac} \\ - inter-unit-product & Literal & \cs{,} \\ - parse-units & Switch & true \\ - per-mode & Choice & power \\ - per-symbol & Literal & / \\ - qualifier-mode & Choice & subscript \\ - qualifier-phrase & Literal & \meta{empty} \\ - sticky-per & Switch & false \\ - unit-font-command & Literal & \cs{mathrm} \\ + bracket-unit-denominator & Switch & true \\ + forbid-literal-units & Switch & false \\ + fraction-command & Literal & \cs{frac} \\ + inter-unit-product & Literal & \cs{,} \\ + parse-units & Switch & true \\ + per-mode & Choice & power \\ + per-symbol-script-correction & Literal & \cs{!} \\ + per-symbol & Literal & / \\ + power-half-as-sqrt & Switch & false \\ + qualifier-mode & Choice & subscript \\ + qualifier-phrase & Literal & \meta{empty} \\ + sticky-per & Switch & false \\ + unit-font-command & Literal & \cs{mathrm} \\ \bottomrule \end{tabular} \end{table} @@ -2207,6 +2356,8 @@ centred dot. To get the correct spacing it is necessary to use \end{LaTeXdemo} \DescribeOption{per-mode} +\DescribeOption{display-per-mode} +\DescribeOption{inline-per-mode} \DescribeOption{per-symbol} \DescribeOption{fraction-command} \DescribeOption{bracket-unit-denominator} @@ -2233,7 +2384,7 @@ unit by setting \opt{per-mode} to \opt{symbol}; the symbol used is stored using the setting \opt{per-symbol}. This method for displaying units can be ambiguous, and so brackets are added unless \opt{bracket-unit-denominator} is set to \opt{false}. Notice that \opt{bracket-unit-denominator} only applies -when \opt{per-mode} is set to \opt{symbol} or \opt{symbol-or-fraction}. +when \opt{per-mode} is set to \opt{symbol}. \begin{LaTeXdemo} \sisetup{per-mode = symbol}% \unit{\joule\per\mole\per\kelvin} \\ @@ -2246,12 +2397,26 @@ is also available to repeat the symbol for each \cs{per}. \begin{LaTeXdemo} \unit[per-mode = repeated-symbol]{\joule\per\mole\per\kelvin} \end{LaTeXdemo} -Finally, it is possible for the behaviour of the \cs{per} function to depend on -the prevailing math style. Setting \opt{per-mode} to \opt{symbol-or-fraction} -will use the \opt{symbol} setting for in line math, and the \opt{fraction} -setting when used in display math. +The use of a symbol can be restricted to the case where exactly one is +required: the setting \opt{single-symbol} will use a symbol if and only +if there are one or more positive powers and exactly one negative power. +In other cases, powers are used. +\begin{LaTeXdemo} + \sisetup{per-mode = single-symbol} + \qty{10}{\per\metre} \\ + \qty{20}{\metre\per\second} \\ + \qty{30}{\joule\per\mole\per\kelvin} +\end{LaTeXdemo} +It is possible for the behaviour of the \cs{per} function to depend on the +prevailing math style. Setting either \opt{display-per-mode} or +\opt{inline-per-mode} independently can be used to achieve this. For example, +the following example will will use the \opt{symbol} setting for in line math, +and the \opt{fraction} setting when used in display math. \begin{LaTeXdemo} - \sisetup{per-mode = symbol-or-fraction}% + \sisetup{ + display-per-mode = fraction , + inline-per-mode = symbol + }% $ \unit{\joule\per\mole\per\kelvin} $ \[ \unit{\joule\per\mole\per\kelvin} \] \unit{\joule\per\mole\per\kelvin} \\ @@ -2265,6 +2430,17 @@ setting when used in display math. \] \end{LaTeXdemo} +\DescribeOption{per-symbol-script-correction} +When using the \opt{symbol} setting for \opt{per-mode}, there may the need to +adjust spacing between a superscript power and the symbol. This is provided as +a command to be inserted between the two items: the standard value is a thin +negative space, \cs{!}. +\begin{LaTeXdemo} + \sisetup{per-mode = symbol}% + \unit{\cm\cubed\per\gram} \\ + \unit[per-symbol-script-correction = ]{\cm\cubed\per\gram} +\end{LaTeXdemo} + \DescribeOption{sticky-per} By default, \cs{per} applies only to the next unit given.\footnote{This is the standard method of reading units in English: for example, @@ -2299,6 +2475,15 @@ example a space or other linking text to be inserted. \unit{\kilogram\of{pol}\squared\per\mole\of{cat}\per\hour} \end{LaTeXdemo} +\DescribeOption{power-half-as-sqrt} +In some cases, the power of $0.5$ is shown by giving the unit symbol as a +square root. This can be enabled by setting \opt{power-half-as-sqrt} to +\opt{true} +\begin{LaTeXdemo} + \unit{\Hz\tothe{0.5}} \\ + \unit[power-half-as-sqrt]{\Hz\tothe{0.5}} +\end{LaTeXdemo} + \DescribeOption{parse-units} Normally, \pkg{siunitx} is used with the unit parse enabled, and only prints units directly if there is literal input. However, if the input is known to be @@ -3028,11 +3213,10 @@ unit which remains accepted. \section{Localisation} -The \pkg{translations} package provides a structured framework for localisation -of words and phrases, and is part of the larger \pkg{beamer} bundle. The -\pkg{translations} package provides the \cs{translate} macro, which will provide -appropriate translations based on the current \pkg{babel} or \pkg{polyglossia} -language setting. +The \pkg{translations} package provides a structured framework for +localisation of words and phrases. In particular, it offers the +\cs{GetTranslation} macro, which will provide appropriate translations based +on the current \pkg{babel} or \pkg{polyglossia} language setting. If \pkg{translations} is available, \pkg{siunitx} will load it and alter the standard settings for the \opt{list-final-separator} and \opt{range-phrase} @@ -3044,9 +3228,10 @@ options to read: range-phrase = { \GetTranslation{to (numerical range)} }, } \end{LaTeXdemo} -If the current language is known to the \pkg{translator} package then the +If the current language is known to the \pkg{translations} package then the result will be localised text. The preamble for this manual loads English, -French, German, Polish and Spanish as options, and also loads the \pkg{babel} package: +French, German, Polish, Spanish, Catalan, Portuguese and Brazilian as options, +and also loads the \pkg{babel} package: \begin{LaTeXdemo} % In English by default \numlist{1;2;3} \\ @@ -3062,6 +3247,15 @@ French, German, Polish and Spanish as options, and also loads the \pkg{babel} pa \numrange{1}{10} \\ \selectlanguage{spanish}% \numlist{1;2;3} \\ + \numrange{1}{10} \\ + \selectlanguage{catalan}% + \numlist{1;2;3} \\ + \numrange{1}{10} \\ + \selectlanguage{portuguese}% + \numlist{1;2;3} \\ + \numrange{1}{10} \\ + \selectlanguage{brazilian}% + \numlist{1;2;3} \\ \numrange{1}{10} \end{LaTeXdemo} @@ -3071,12 +3265,14 @@ In general, \pkg{siunitx} should be usable with other packages without interference. When the \pkg{physics} package is loaded before \pkg{siunitx}, the command -\cs{qty} is not defined: users will need to use the version~$2$ command -\cs{SI}. - -When the \pkg{units} package is loaded before \pkg{siunitx}, the command -\cs{unit} is not defined: users will need to use the version~$2$ command -\cs{si}. +\cs{qty} is not defined. Users may use the version~$2$ command \cs{SI}, +which can be used as a drop-in replacement for \cs{qty}. Alternatively, +if the \pkg{siunitx} definition is preferred, you may use +\begin{LaTeXdemo}[code only] + \AtBeginDocument{\RenewCommandCopy\qty\SI} +\end{LaTeXdemo} +and use the longer name \cs{quantity} to access the functionality of the +\pkg{physics} package. \section{Hints for using \pkg{siunitx}} @@ -3391,7 +3587,7 @@ systems: \end{LaTeXdemo} For tables, any settings that can be given before the table are only parsed once, -whereas given in the optional argument to |S| they are read in ever cell. As such, +whereas given in the optional argument to |S| they are read in every cell. As such, you should favour \begin{LaTeXdemo}[code only] \begin{table} diff --git a/Master/texmf-dist/tex/latex/siunitx/siunitx.sty b/Master/texmf-dist/tex/latex/siunitx/siunitx.sty index a25a2cbc1d3..96851bb721a 100644 --- a/Master/texmf-dist/tex/latex/siunitx/siunitx.sty +++ b/Master/texmf-dist/tex/latex/siunitx/siunitx.sty @@ -42,7 +42,7 @@ }% \endinput }% -\ProvidesExplPackage {siunitx} {2022-04-04} {3.0.50} +\ProvidesExplPackage {siunitx} {2022-04-25} {3.1.0} {A comprehensive (SI) units package} \msg_new:nnnn { siunitx } { incompatible-package } { Package~'#1'~incompatible. } @@ -54,11 +54,11 @@ { } } \clist_map_function:nN - { SIunits , sistyle , unitsdef , fancyunits } + { SIunits , sistyle , units , unitsdef , fancyunits } \__siunitx_load_check:n \AtBeginDocument { - \clist_map_function:nN { SIunits , sistyle } + \clist_map_function:nN { SIunits , sistyle , units } \__siunitx_load_check:n } \providecommand \IfFormatAtLeastTF { \@ifl@t@r \fmtversion } @@ -361,16 +361,46 @@ \tl_new:N \l__siunitx_complex_exp_tl \tl_new:N \l__siunitx_complex_real_tl \tl_new:N \l__siunitx_complex_img_tl +\tl_new:N \l__siunitx_complex_mag_tl +\tl_new:N \l__siunitx_complex_angle_tl \tl_new:N \l__siunitx_complex_join_tl \tl_new:N \l__siunitx_complex_sign_tl \bool_new:N \l__siunitx_complex_root_after_bool +\bool_new:N \l__siunitx_complex_force_cartesian_bool +\bool_new:N \l__siunitx_complex_force_polar_bool +\bool_new:N \l__siunitx_complex_polar_degree_bool \keys_define:nn { siunitx } { + complex-mode .choice: , + complex-mode / cartesian .code:n = + { + \bool_set_true:N \l__siunitx_complex_force_cartesian_bool + \bool_set_false:N \l__siunitx_complex_force_polar_bool + } , + complex-mode / polar .code:n = + { + \bool_set_false:N \l__siunitx_complex_force_cartesian_bool + \bool_set_true:N \l__siunitx_complex_force_polar_bool + } , + complex-mode / input .code:n = + { + \bool_set_false:N \l__siunitx_complex_force_cartesian_bool + \bool_set_false:N \l__siunitx_complex_force_polar_bool + } , + complex-angle-unit .choice: , + complex-angle-unit / degrees .code:n = + { \bool_set_true:N \l__siunitx_complex_polar_degree_bool } , + complex-angle-unit / radians .code:n = + { \bool_set_false:N \l__siunitx_complex_polar_degree_bool } , complex-root-position .choice: , complex-root-position / after-number .code:n = { \bool_set_true:N \l__siunitx_complex_root_after_bool } , complex-root-position / before-number .code:n = { \bool_set_false:N \l__siunitx_complex_root_after_bool } , + complex-symbol-angle .tl_set:N = + \l__siunitx_complex_symbol_angle_tl , + complex-symbol-degree .tl_set:N = + \l__siunitx_complex_symbol_degree_tl , input-complex-root .tl_set:N = \l__siunitx_complex_input_root_tl , output-complex-root .tl_set:N = @@ -405,33 +435,19 @@ } \cs_new_protected:Npn \__siunitx_complex_parse_check: { - \bool_lazy_all:nTF - { - { \tl_if_empty_p:N \l__siunitx_complex_real_tl } - { \tl_if_empty_p:N \l__siunitx_complex_img_tl } - { \tl_if_empty_p:N \l__siunitx_complex_exp_tl } - } - { - \msg_error:nnx { siunitx } { invalid-complex-number } - { \exp_not:V \l__siunitx_complex_input_tl } - } - { \__siunitx_complex_parse_finalise: } - } -\cs_new_protected:Npn \__siunitx_complex_parse_finalise: - { \tl_if_empty:NTF \l__siunitx_complex_img_tl - { \__siunitx_complex_parse_finalise:N \l__siunitx_complex_real_tl } + { \__siunitx_complex_parse_check:N \l__siunitx_complex_real_tl } { \tl_if_empty:NTF \l__siunitx_complex_real_tl - { \__siunitx_complex_parse_finalise:N \l__siunitx_complex_img_tl } + { \__siunitx_complex_parse_check:N \l__siunitx_complex_img_tl } { - \__siunitx_complex_parse_finalise:N \l__siunitx_complex_real_tl + \__siunitx_complex_parse_check:N \l__siunitx_complex_real_tl \tl_set_eq:NN \l__siunitx_complex_sign_tl \l__siunitx_complex_join_tl - \__siunitx_complex_parse_finalise:N \l__siunitx_complex_img_tl + \__siunitx_complex_parse_check:N \l__siunitx_complex_img_tl } } } -\cs_new_protected:Npn \__siunitx_complex_parse_finalise:N #1 +\cs_new_protected:Npn \__siunitx_complex_parse_check:N #1 { \tl_set:Nx #1 { @@ -618,6 +634,21 @@ \tl_if_empty:NT \l__siunitx_complex_real_tl { \__siunitx_complex_parse_clear: } } +\cs_new_protected:Npn \__siunitx_complex_parse_polar:nn #1#2 + { + \siunitx_number_parse:nN {#1} \l__siunitx_complex_mag_tl + \group_begin: + \keys_set:nn { siunitx } + { + input-comparators = , + input-exponent-markers = , + input-open-uncertainty = , + input-close-uncertainty = + } + \siunitx_number_format:nN {#2} \l__siunitx_complex_angle_tl + \exp_args:NNNV \group_end: + \tl_set:Nn \l__siunitx_complex_angle_tl \l__siunitx_complex_angle_tl + } \tl_new:N \l__siunitx_complex_bracket_close_tl \tl_new:N \l__siunitx_complex_bracket_open_tl \tl_set:Nn \l__siunitx_complex_bracket_open_tl { ( } @@ -625,37 +656,101 @@ \tl_new:N \l__siunitx_complex_unit_tl \cs_new_protected:Npn \siunitx_complex_number:n #1 { - \group_begin: - \bool_if:NTF \l_siunitx_number_parse_bool - { - \__siunitx_complex_parse:nNN {#1} \l__siunitx_complex_real_tl \l__siunitx_complex_img_tl - \__siunitx_complex_format:n { } - } - { - \siunitx_number_format:nN {#1} \l__siunitx_complex_tmp_tl - \siunitx_print_number:V \l__siunitx_complex_tmp_tl - } - \group_end: + \bool_if:NTF \l__siunitx_complex_force_polar_bool + { + \use:e + { + \siunitx_complex_number:nn + \__siunitx_complex_convert_polar:n {#1} + } + } + { + \bool_if:NTF \l_siunitx_number_parse_bool + { + \__siunitx_complex_parse:nNN {#1} \l__siunitx_complex_real_tl \l__siunitx_complex_img_tl + \__siunitx_complex_format_cartesian:n { } + } + { + \siunitx_number_format:nN {#1} \l__siunitx_complex_tmp_tl + \siunitx_print_number:V \l__siunitx_complex_tmp_tl + } + } + } +\cs_new_protected:Npn \siunitx_complex_number:nn #1#2 + { + \bool_lazy_or:nnTF + { \tl_if_blank_p:n {#1} } + { \tl_if_blank_p:n {#2} } + { + \msg_error:nnnn { siunitx } { invalid-polar-form } + {#1} {#2} + } + { \__siunitx_complex_number:nn {#1} {#2} } + } +\cs_new_protected:Npn \__siunitx_complex_number:nn #1#2 + { + \bool_if:NTF \l__siunitx_complex_force_cartesian_bool + { + \exp_args:Ne \siunitx_complex_number:n + { \__siunitx_complex_convert_cartesian:nn {#1} {#2} } + } + { + \__siunitx_complex_parse_polar:nn {#1} {#2} + \__siunitx_complex_format_polar:n { } + } } \cs_new_protected:Npn \siunitx_complex_quantity:nn #1#2 { - \group_begin: - \bool_if:NTF \l_siunitx_number_parse_bool - { - \__siunitx_complex_parse:nNN {#1} \l__siunitx_complex_real_tl \l__siunitx_complex_img_tl - \__siunitx_complex_format:n {#2} - } - { \siunitx_quantity:nn {#1} {#2} } - \group_end: + \bool_if:NTF \l__siunitx_complex_force_polar_bool + { + \use:e + { + \siunitx_complex_quantity:nnn + \__siunitx_complex_convert_polar:n {#1} + } + {#2} + } + { + \bool_if:NTF \l_siunitx_number_parse_bool + { + \__siunitx_complex_parse:nNN {#1} \l__siunitx_complex_real_tl \l__siunitx_complex_img_tl + \__siunitx_complex_format_cartesian:n {#2} + } + { \siunitx_quantity:nn {#1} {#2} } + } + } +\cs_new_protected:Npn \siunitx_complex_quantity:nnn #1#2#3 + { + \bool_lazy_or:nnTF + { \tl_if_blank_p:n {#1} } + { \tl_if_blank_p:n {#2} } + { + \msg_error:nnnn { siunitx } { invalid-polar-form } + {#1} {#2} + } + { \__siunitx_complex_quantity:nnn {#1} {#2} {#3} } + } +\cs_new_protected:Npn \__siunitx_complex_quantity:nnn #1#2#3 + { + \bool_if:NTF \l__siunitx_complex_force_cartesian_bool + { + \exp_args:Ne \siunitx_complex_quantity:nn + { \__siunitx_complex_convert_cartesian:nn {#1} {#2} } + {#3} + } + { + \__siunitx_complex_parse_polar:nn {#1} {#2} + \__siunitx_complex_format_polar:n {#3} + } } -\cs_new_protected:Npn \__siunitx_complex_format:n #1 +\cs_new_protected:Npn \__siunitx_complex_format_cartesian:n #1 { \bool_lazy_and:nnF { \tl_if_empty_p:N \l__siunitx_complex_real_tl } { \tl_if_empty_p:N \l__siunitx_complex_img_tl } - { \__siunitx_complex_format_auxi:n {#1} } + { \__siunitx_complex_format_cartesian_auxi:n {#1} } } -\cs_new_protected:Npn \__siunitx_complex_format_auxi:n #1 +\cs_new_protected:Npn \__siunitx_complex_format_cartesian_auxi:n #1 { \tl_clear:N \l__siunitx_complex_tmp_tl \tl_if_empty:NTF \l__siunitx_complex_img_tl @@ -664,14 +759,14 @@ \tl_set:Nx \l__siunitx_complex_tmp_tl { \siunitx_number_output:N \l__siunitx_complex_real_tl } } - { \__siunitx_complex_format_auxii:n {#1} } + { \__siunitx_complex_format_cartesian_auxii:n {#1} } \tl_if_blank:nTF {#1} { \siunitx_print_number:V \l__siunitx_complex_tmp_tl } { \siunitx_quantity_print:VV \l__siunitx_complex_tmp_tl \l__siunitx_complex_unit_tl } } -\cs_new_protected:Npn \__siunitx_complex_format_auxii:n #1 +\cs_new_protected:Npn \__siunitx_complex_format_cartesian_auxii:n #1 { - \__siunitx_complex_format_units:n {#1} + \__siunitx_complex_format_cartesian_units:n {#1} \tl_if_empty:NF \l__siunitx_complex_real_tl { \exp_after:wN \__siunitx_complex_drop_exponent:nnnnnnn \l__siunitx_complex_real_tl } \exp_after:wN \__siunitx_complex_format_sign:nnnnnnn \l__siunitx_complex_img_tl @@ -754,7 +849,7 @@ #1 \exp_not:V \l__siunitx_complex_bracket_close_tl } -\cs_new_protected:Npn \__siunitx_complex_format_units:n #1 +\cs_new_protected:Npn \__siunitx_complex_format_cartesian_units:n #1 { \tl_if_blank:nTF {#1} { @@ -762,10 +857,11 @@ \siunitx_number_process:NN \l__siunitx_complex_img_tl \l__siunitx_complex_img_tl } { - \use:c { __siunitx_complex_format_ \l_siunitx_quantity_prefix_mode_tl :n } {#1} + \use:c + { __siunitx_complex_format_cartesian_ \l_siunitx_quantity_prefix_mode_tl :n } {#1} } } -\cs_new_protected:cpn { __siunitx_complex_format_combine-exponent:n } #1 +\cs_new_protected:cpn { __siunitx_complex_format_cartesian_combine-exponent:n } #1 { \tl_if_empty:NF \l__siunitx_complex_real_tl { \siunitx_number_process:NN \l__siunitx_complex_real_tl \l__siunitx_complex_real_tl } @@ -777,7 +873,7 @@ \siunitx_unit_format_combine_exponent:nnN {#1} \l__siunitx_complex_tmp_fp \l__siunitx_complex_unit_tl } -\cs_new_protected:cpx { __siunitx_complex_format_extract-exponent:n } #1 +\cs_new_protected:cpx { __siunitx_complex_format_cartesian_extract-exponent:n } #1 { \exp_not:N \siunitx_unit_format_extract_prefixes:nNN {#1} \exp_not:N \l__siunitx_complex_unit_tl \exp_not:N \l__siunitx_complex_tmp_fp @@ -789,32 +885,169 @@ \exp_not:N \l__siunitx_complex_real_tl } } +\cs_new_protected:Npn \__siunitx_complex_format_cartesian_input:n #1 + { + \siunitx_number_process:NN \l__siunitx_complex_real_tl \l__siunitx_complex_real_tl + \siunitx_number_process:NN \l__siunitx_complex_img_tl \l__siunitx_complex_img_tl + \siunitx_unit_format:nN {#1} \l__siunitx_complex_unit_tl + } \cs_new_protected:cpn { __siunitx_complex_format_extract-exponent:N } #1 { \tl_set:Nx #1 { \siunitx_number_adjust_exponent:Nn #1 \l__siunitx_complex_tmp_fp } \siunitx_number_process:NN #1 #1 } -\cs_new_protected:Npn \__siunitx_complex_format_input:n #1 - { - \siunitx_number_process:NN \l__siunitx_complex_real_tl \l__siunitx_complex_real_tl - \siunitx_number_process:NN \l__siunitx_complex_img_tl \l__siunitx_complex_img_tl - \siunitx_unit_format:nN {#1} \l__siunitx_complex_unit_tl - } \cs_new:Npn \__siunitx_complex_extract_exp:nnnnnnn #1#2#3#4#5#6#7 { #6#7 } \cs_new_protected:Npn \__siunitx_complex_drop_exp:N #1 { \exp_after:wN \__siunitx_complex_drop_exp:nnnnnnnN #1 #1 } \cs_new_protected:Npn \__siunitx_complex_drop_exp:nnnnnnnN #1#2#3#4#5#6#7#8 { \tl_set:Nn #8 { {#1} {#2} {#3} {#4} {#5} { } { 0 } } } -\msg_new:nnnn { siunitx } { invalid-complex-number } - { Invalid~complex-number~'#1'. } +\cs_new_protected:Npn \__siunitx_complex_format_polar:n #1 { - The~input~'#1'~could~not~be~parsed~as~a~complex|number~following~the~ - format~defined~in~module~documentation. + \tl_if_blank:nTF {#1} + { \siunitx_number_process:NN \l__siunitx_complex_mag_tl \l__siunitx_complex_mag_tl } + { + \use:c + { __siunitx_complex_format_polar_ \l_siunitx_quantity_prefix_mode_tl :n } {#1} + } + \tl_set:Nx \l__siunitx_complex_tmp_tl + { + \siunitx_number_output:N \l__siunitx_complex_mag_tl + \exp_not:V \l__siunitx_complex_symbol_angle_tl + \mathord % TEMP + \exp_not:V \l__siunitx_complex_angle_tl + } + \siunitx_print_number:V \l__siunitx_complex_tmp_tl + \bool_if:NT \l__siunitx_complex_polar_degree_bool + { + \exp_args:NV \siunitx_unit_format:nN \l__siunitx_complex_symbol_degree_tl \l__siunitx_complex_tmp_tl + \nobreak + \siunitx_print_unit:V \l__siunitx_complex_tmp_tl + } + \siunitx_quantity_print:nV { } \l__siunitx_complex_unit_tl + } +\cs_new_protected:cpn { __siunitx_complex_format_polar_combine-exponent:n } #1 + { + \siunitx_number_process:NN \l__siunitx_complex_mag_tl \l__siunitx_complex_mag_tl + \fp_set:Nn \l__siunitx_complex_tmp_fp + { \exp_after:wN \__siunitx_complex_extract_exp:nnnnnnn \l__siunitx_complex_mag_tl } + \__siunitx_complex_drop_exp:N \l__siunitx_complex_mag_tl + \siunitx_unit_format_combine_exponent:nnN {#1} + \l__siunitx_complex_tmp_fp \l__siunitx_complex_unit_tl + } +\cs_new_protected:cpx { __siunitx_complex_format_polar_extract-exponent:n } #1 + { + \exp_not:N \siunitx_unit_format_extract_prefixes:nNN {#1} + \exp_not:N \l__siunitx_complex_unit_tl \exp_not:N \l__siunitx_complex_tmp_fp + \exp_not:c { __siunitx_complex_format_extract-exponent:N } + \exp_not:N \l__siunitx_complex_mag_tl + } +\cs_new_protected:Npn \__siunitx_complex_format_polar_input:n #1 + { + \siunitx_number_process:NN \l__siunitx_complex_mag_tl \l__siunitx_complex_mag_tl + \siunitx_unit_format:nN {#1} \l__siunitx_complex_unit_tl + } +\cs_new:Npn \__siunitx_complex_convert_cartesian:nn #1#2 + { + \exp_args:Nee \__siunitx_complex_convert_cartesian_aux:nn + { + \fp_to_tl:n + { (#1) * cos \bool_if:NT \l__siunitx_complex_polar_degree_bool { d } (#2) } + } + { + \fp_to_tl:n + { (#1) * sin \bool_if:NT \l__siunitx_complex_polar_degree_bool { d } (#2) } + } + } +\cs_new:Npn \__siunitx_complex_convert_cartesian_aux:nn #1#2 + { + \__siunitx_complex_convert_cartesian_aux:w #1 e e \q_mark #2 e e \q_stop + } +\cs_new:Npn \__siunitx_complex_convert_cartesian_aux:w + #1 e #2 e #3 \q_mark #4 e #5 e #6 \q_stop + { + \fp_compare:nNnF {#1} = \c_zero_fp + {#1} + \fp_compare:nNnF {#4} = \c_zero_fp + { + \fp_compare:nNnF {#4} < \c_zero_fp { + } + #4 i + } + \tl_if_blank:nF {#2} + { e #2 } + } +\cs_new:Npn \__siunitx_complex_convert_polar:n #1 + { \__siunitx_complex_convert_polar_auxi:w #1 e e \q_stop } +\cs_new:Npn \__siunitx_complex_convert_polar_auxi:w #1 e #2 e #3 \q_stop + { \__siunitx_complex_convert_polar_auxii:nw {#2} #1 \q_stop } +\cs_new:Npn \__siunitx_complex_convert_polar_auxii:nw #1#2#3 \q_stop + { + \bool_lazy_or:nnTF + { \str_if_eq_p:nn {#2} { i } } + { \str_if_eq_p:nn {#2#3} { +i } } + { \__siunitx_complex_convert_polar_auxvi:nnn { } { 1 } {#1} } + { + \str_if_eq:nnTF {#2#3} { -i } + { \__siunitx_complex_convert_polar_auxvi:nnn { } { -1 } {#1} } + { \__siunitx_complex_convert_polar_auxiii:nnw {#1} {#2} #3 + + \q_stop } + } + } +\cs_new:Npn \__siunitx_complex_convert_polar_auxiii:nnw #1#2#3 + #4 + #5 \q_stop + { + \tl_if_blank:nTF {#4} + { \__siunitx_complex_convert_polar_auxiv:nnw {#1} {#2} #3 - - \q_stop } + { + \str_if_eq:nnTF {#4} { i } + { \__siunitx_complex_convert_polar_auxvi:nnn {#2#3} { 1 } {#1} } + { \__siunitx_complex_convert_polar_auxv:nnw {#2#3} {#1} #4 i \q_nil i \q_stop } + } + } +\cs_new:Npn \__siunitx_complex_convert_polar_auxiv:nnw #1#2#3 - #4 - #5 \q_stop + { + \tl_if_blank:nTF {#4} + { \__siunitx_complex_convert_polar_auxv:nnw { } {#1} #2#3 i \q_nil i \q_stop } + { + \str_if_eq:nnTF {#4} { i } + { \__siunitx_complex_convert_polar_auxvi:nnn { } { -1 } {#1} } + { \__siunitx_complex_convert_polar_auxv:nnw {#2#3} {#1} -#4 i \q_nil i \q_stop } + } + } +\cs_new:Npn \__siunitx_complex_convert_polar_auxv:nnw #1#2#3 i #4 i #5 \q_stop + { + \quark_if_nil:nTF {#4} + { { #3 \tl_if_blank:nF {#2} { e#2 } } { 0 } } + { \__siunitx_complex_convert_polar_auxvi:nnn {#1} {#3} {#2} } + } +\cs_new:Npn \__siunitx_complex_convert_polar_auxvi:nnn #1#2#3 + { + \exp_args:Neee \__siunitx_complex_convert_polar_auxvii:nnn + { \tl_if_blank:nTF {#1} { 0 } {#1} } + { \tl_if_blank:nTF {#2} { 0 } {#2} } + { \tl_if_blank:nF {#3} { e#3 } } + } +\cs_new:Npn \__siunitx_complex_convert_polar_auxvii:nnn #1#2#3 + { + \exp_args:Nee \__siunitx_complex_format_polar_auxviii:nn + { \fp_eval:n { sqrt ( (#1#3)^2 + (#2#3)^2 ) } } + { + \fp_eval:n + { atan \bool_if:NT \l__siunitx_complex_polar_degree_bool { d } (#2 , #1) } + } + } +\cs_new:Npn \__siunitx_complex_format_polar_auxviii:nn #1#2 { {#1} {#2} } +\msg_new:nnnn { siunitx } { invalid-polar-form } + { Invalid~polar~form~"#1:#2". } + { + Complex~numbers~in~polar~form~must~have~both~a~magnitude~and~and~ + angle. } \keys_set:nn { siunitx } { + complex-angle-unit = degrees , + complex-mode = input , complex-root-position = after-number , + complex-symbol-angle = \angle , + complex-symbol-degree = \degree , input-complex-root = ij , output-complex-root = \mathrm { i } } @@ -1467,15 +1700,18 @@ \file_if_exist:nT { translations.sty } { \RequirePackage { translations } - \DeclareTranslation { Catalan } { and } { i } - \DeclareTranslation { Slovene } { and } { in } - \DeclareTranslation { Catalan } { to~(numerical~range) } { a } - \DeclareTranslation { English } { to~(numerical~range) } { to } - \DeclareTranslation { French } { to~(numerical~range) } { Ã } - \DeclareTranslation { German } { to~(numerical~range) } { bis } - \DeclareTranslation { Polish } { to~(numerical~range) } { do } - \DeclareTranslation { Slovene } { to~(numerical~range) } { do } - \DeclareTranslation { Spanish } { to~(numerical~range) } { a } + \DeclareTranslation { Catalan } { and } { i } + \DeclareTranslation { Slovene } { and } { in } + \DeclareTranslation { Portuguese } { and } { e } + \DeclareTranslation { Catalan } { to~(numerical~range) } { a } + \DeclareTranslation { English } { to~(numerical~range) } { to } + \DeclareTranslation { French } { to~(numerical~range) } { Ã } + \DeclareTranslation { German } { to~(numerical~range) } { bis } + \DeclareTranslation { Polish } { to~(numerical~range) } { do } + \DeclareTranslation { Slovene } { to~(numerical~range) } { do } + \DeclareTranslation { Spanish } { to~(numerical~range) } { a } + \DeclareTranslation { Brazilian } { to~(numerical~range) } { a } + \DeclareTranslation { Portuguese } { to~(numerical~range) } { a } \keys_set:nn { siunitx } { list-final-separator = @@ -1562,6 +1798,8 @@ \l__siunitx_number_explicit_decimal_bool , retain-explicit-plus .bool_set:N = \l__siunitx_number_explicit_plus_bool , + retain-negative-zero .bool_set:N = + \l__siunitx_number_negative_zero_bool , retain-zero-uncertainty .bool_set:N = \l__siunitx_number_zero_uncert_bool } @@ -1574,6 +1812,7 @@ \tl_new:N \l__siunitx_number_parsed_tl \tl_new:N \l__siunitx_number_input_tl \tl_new:N \l__siunitx_number_partial_tl +\tl_new:N \l__siunitx_number_uncert_tl \bool_new:N \l__siunitx_number_validate_bool \cs_new_protected:Npn \siunitx_number_normalize_symbols:N #1 { @@ -1617,6 +1856,7 @@ { \group_begin: \tl_clear:N \l__siunitx_number_parsed_tl + \tl_clear:N \l__siunitx_number_uncert_tl \tl_map_inline:Nn \l__siunitx_number_input_ignore_tl { \token_if_macro:NT ##1 @@ -1640,25 +1880,11 @@ } \cs_new_protected:Npn \__siunitx_number_parse_check: { - \tl_if_empty:NF \l__siunitx_number_flex_tl + \tl_put_right:NV \l__siunitx_number_uncert_tl \l__siunitx_number_flex_tl + \tl_if_empty:NF \l__siunitx_number_uncert_tl { - \bool_lazy_and:nnTF - { - \tl_if_blank_p:f - { \exp_after:wN \use_iv:nnnn \l__siunitx_number_parsed_tl } - } - { - \tl_if_blank_p:f - { \exp_after:wN \use_iv:nnnn \l__siunitx_number_flex_tl } - } - { - \tl_set:Nx \l__siunitx_number_tmp_tl - { \exp_after:wN \use_i:nnnn \l__siunitx_number_flex_tl } - \tl_if_in:NVTF \l__siunitx_number_input_uncert_sign_tl - \l__siunitx_number_tmp_tl - { \__siunitx_number_parse_combine_uncert: } - { \tl_clear:N \l__siunitx_number_parsed_tl } - } + \tl_if_blank:fTF { \exp_after:wN \use_iv:nnnn \l__siunitx_number_parsed_tl } + { \__siunitx_number_parse_combine_uncert: } { \tl_clear:N \l__siunitx_number_parsed_tl } } \tl_if_empty:NTF \l__siunitx_number_parsed_tl @@ -1673,74 +1899,102 @@ } \cs_new_protected:Npn \__siunitx_number_parse_combine_uncert: { - \exp_after:wN \exp_after:wN \exp_after:wN - \__siunitx_number_parse_combine_uncert_auxi:nnnnnnnn - \exp_after:wN \l__siunitx_number_parsed_tl \l__siunitx_number_flex_tl + \tl_set:Nx \l__siunitx_number_parsed_tl + { + \exp_after:wN \__siunitx_number_parse_combine_uncert:nnnn + \l__siunitx_number_parsed_tl + } + } +\cs_new:Npn \__siunitx_number_parse_combine_uncert:nnnn #1#2#3#4 + { + \exp_after:wN \__siunitx_number_parse_combine_uncert:nn + \exp_after:wN { \l__siunitx_number_uncert_tl } {#3} } -\cs_new_protected:Npn - \__siunitx_number_parse_combine_uncert_auxi:nnnnnnnn #1#2#3#4#5#6#7#8 +\cs_new:Npn \__siunitx_number_parse_combine_uncert:nn #1#2 { - \__siunitx_number_parse_combine_uncert_auxii:fnnnn - { \int_eval:n { \tl_count:n {#3} - \tl_count:n {#7} } } - {#2} {#3} {#6} {#7} + \__siunitx_number_parse_combine_uncert_loop:nnnnnnn {#2} { } { } + #1 + { \q_recursion_tail } { } { } { } \q_recursion_stop } -\cs_new_protected:Npn - \__siunitx_number_parse_combine_uncert_auxii:nnnnn #1 +\cs_new:Npn \__siunitx_number_parse_combine_uncert_loop:nnnnnnn #1#2#3#4#5#6#7 { - \__siunitx_number_parse_combine_uncert_auxiii:fnnnnn + \quark_if_recursion_tail_stop_do:nn {#4} + { \__siunitx_number_parse_combine_uncert_end:nnn {#1} {#2} {#3} } + \exp_args:Nf \__siunitx_number_parse_combine_uncert:nnnnnn + { \int_eval:n { \tl_count:n {#1} - \tl_count:n {#6} } } + {#1} {#2} {#3} {#5} {#6} + } +\cs_new:Npn \__siunitx_number_parse_combine_uncert:nnnnnn #1 + { + \exp_args:Nf \__siunitx_number_parse_combine_uncert:nnnnnnn { \prg_replicate:nn { \int_abs:n {#1} } { 0 } } {#1} } -\cs_generate_variant:Nn \__siunitx_number_parse_combine_uncert_auxii:nnnnn { f } -\cs_new_protected:Npn - \__siunitx_number_parse_combine_uncert_auxiii:nnnnnn #1#2#3#4#5#6 +\cs_new:Npn \__siunitx_number_parse_combine_uncert:nnnnnnn #1#2#3#4#5#6#7 { \int_compare:nNnTF {#2} > 0 { - \__siunitx_number_parse_combine_uncert_auxiv:nnnn - {#3} {#4} {#5} { #6 #1 } + \__siunitx_number_parse_combine_uncert:nnnnn + {#3} {#4} {#5} {#6} { #7 #1 } } { - \__siunitx_number_parse_combine_uncert_auxiv:nnnn - {#3} { #4 #1 } {#5} {#6} + \__siunitx_number_parse_combine_uncert:nnnnn + { #3 #1 } {#4} {#5} {#6} {#7} } } -\cs_generate_variant:Nn - \__siunitx_number_parse_combine_uncert_auxiii:nnnnnn { f } -\cs_new_protected:Npn - \__siunitx_number_parse_combine_uncert_auxiv:nnnn #1#2#3#4 +\cs_new:Npn \__siunitx_number_parse_combine_uncert:nnnnn #1#2#3#4#5 { - \tl_set:Nx \l__siunitx_number_parsed_tl + \exp_args:Nee \__siunitx_number_parse_combine_uncert_aux:nnnn { - { \tl_head:V \l__siunitx_number_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} } - } - { - \__siunitx_number_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} } + } + { + \__siunitx_number_parse_combine_uncert:N #4#5 + \q_recursion_tail \q_recursion_stop + } + {#2} + {#3} } -\cs_new:Npn \__siunitx_number_parse_combine_uncert_auxv:w #1 +\cs_new:Npn \__siunitx_number_parse_combine_uncert_aux:nnnn #1#2#3#4 { - \quark_if_recursion_tail_stop_do:Nn #1 + \exp_args:Neee \__siunitx_number_parse_combine_uncert_loop:nnnnnnn + { \exp_not:n {#1} } + { + \exp_not:n {#3} + \tl_if_blank:nF {#2} { S } + } { - \bool_if:NT \l__siunitx_number_zero_uncert_bool - { { S } { 0 } } + \exp_not:n {#4} + \tl_if_blank:nF {#2} { { \exp_not:n {#2} } } } + } +\cs_new:Npn \__siunitx_number_parse_combine_uncert:N #1 + { + \quark_if_recursion_tail_stop_do:Nn #1 + { \bool_if:NT \l__siunitx_number_zero_uncert_bool { 0 } } \str_if_eq:nnTF {#1} { 0 } - { \__siunitx_number_parse_combine_uncert_auxv:w } - { \__siunitx_number_parse_combine_uncert_auxvi:w #1 } + { \__siunitx_number_parse_combine_uncert:N } + { \__siunitx_number_parse_combine_uncert:w #1 } } -\cs_new:Npn \__siunitx_number_parse_combine_uncert_auxvi:w +\cs_new:Npn \__siunitx_number_parse_combine_uncert:w #1 \q_recursion_tail \q_recursion_stop - { { S } { \exp_not:n {#1} } } + { \exp_not:n {#1} } +\cs_new:Npn \__siunitx_number_parse_combine_uncert_end:nnn #1#2#3 + { + \exp_after:wN \__siunitx_number_parse_combine_uncert_end:nnnn + \l__siunitx_number_parsed_tl + { \exp_not:n {#1} } + { + \tl_if_blank:nF {#2} + { \exp_not:n { {#2} #3 } } + } + } +\cs_new:Npn \__siunitx_number_parse_combine_uncert_end:nnnn #1#2#3#4 + { \exp_not:n { {#1} {#2} } } \cs_new_protected:Npn \__siunitx_number_parse_comparator: { \exp_after:wN \__siunitx_number_parse_comparator_aux:Nw @@ -1855,12 +2109,28 @@ \tl_set:Nx \l__siunitx_number_parsed_tl { { \exp_not:V \l__siunitx_number_comparator_tl } - \exp_not:V \l__siunitx_number_parsed_tl + \exp_after:wN \__siunitx_number_parse_finalise:nnnn \l__siunitx_number_parsed_tl \exp_after:wN \__siunitx_number_parse_finalise:nw \l__siunitx_number_exponent_tl \q_stop } } } +\cs_new:Npn \__siunitx_number_parse_finalise:nnnn #1#2#3#4 + { + \bool_lazy_all:nTF + { + { ! \l__siunitx_number_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 \__siunitx_number_parse_finalise:nw #1#2 \q_stop { { \exp_not:n {#1} } @@ -1880,49 +2150,45 @@ { \bool_if:NTF #2 { \tl_put_right:Nn #1 { { } { } { } } } - { \__siunitx_number_parse_loop_break:wN \q_recursion_stop } + { \__siunitx_number_parse_loop_break:w \q_recursion_stop } } \tl_if_in:NnTF \l__siunitx_number_input_digit_tl {#3} { - \__siunitx_number_parse_loop_main:NNNNN - #1 \c_true_bool \c_false_bool #2 #3 + \__siunitx_number_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 } } - \__siunitx_number_parse_loop_after_decimal:NNN #1 #2 + \__siunitx_number_parse_loop_after_decimal:NN #1 } - { \__siunitx_number_parse_loop_break:wN } + { \__siunitx_number_parse_loop_break:w } } } -\cs_new_protected:Npn \__siunitx_number_parse_loop_main:NNNNN #1#2#3#4#5 +\cs_new_protected:Npn \__siunitx_number_parse_loop_main:NNNN #1#2#3#4 { - \quark_if_recursion_tail_stop_do:Nn #5 + \quark_if_recursion_tail_stop_do:Nn #4 { \__siunitx_number_parse_loop_main_end:NN #1#2 } - \tl_if_in:NnTF \l__siunitx_number_input_digit_tl {#5} - { \__siunitx_number_parse_loop_main_digit:NNNNN #1#2#3#4#5 } + \tl_if_in:NnTF \l__siunitx_number_input_digit_tl {#4} + { \__siunitx_number_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 - { \__siunitx_number_parse_loop_main_decimal:NN #1 #4 } - { \__siunitx_number_parse_loop_break:wN } + { \__siunitx_number_parse_loop_main_decimal:N #1 } + { \__siunitx_number_parse_loop_break:w } } { - \tl_if_in:NnTF \l__siunitx_number_input_uncert_open_tl {#5} - { \__siunitx_number_parse_loop_main_uncert:NNN #1#2 #4 } + \tl_if_in:NnTF \l__siunitx_number_input_uncert_open_tl {#4} + { \__siunitx_number_parse_loop_main_uncert:NN #1 #2 } { - \bool_if:NTF #4 + \tl_if_in:NnTF \l__siunitx_number_input_uncert_sign_tl {#4} { - \tl_if_in:NnTF \l_siunitx_number_input_sign_tl {#5} - { - \__siunitx_number_parse_loop_main_sign:NNN - #1#2 #5 - } - { \__siunitx_number_parse_loop_break:wN } + \__siunitx_number_parse_loop_main_sign:NNN + #1 #2 #4 } - { \__siunitx_number_parse_loop_break:wN } + { \__siunitx_number_parse_loop_break:w } } } } @@ -1945,65 +2211,69 @@ { } } } -\cs_new_protected:Npn \__siunitx_number_parse_loop_main_digit:NNNNN #1#2#3#4#5 +\cs_new_protected:Npn \__siunitx_number_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__siunitx_number_partial_tl {#5} - \__siunitx_number_parse_loop_main:NNNNN #1 #2 \c_true_bool #4 + \tl_put_right:Nn \l__siunitx_number_partial_tl {#4} + \__siunitx_number_parse_loop_main:NNNN #1 #2 \c_true_bool } - { \__siunitx_number_parse_loop_main:NNNNN #1 #2 \c_false_bool #4 } + { \__siunitx_number_parse_loop_main:NNNN #1 #2 \c_false_bool } } -\cs_new_protected:Npn \__siunitx_number_parse_loop_main_decimal:NN #1#2 +\cs_new_protected:Npn \__siunitx_number_parse_loop_main_decimal:N #1 { \__siunitx_number_parse_loop_main_store:NNN #1 \c_false_bool \c_false_bool - \__siunitx_number_parse_loop_after_decimal:NNN #1 #2 + \__siunitx_number_parse_loop_after_decimal:NN #1 } -\cs_new_protected:Npn \__siunitx_number_parse_loop_main_uncert:NNN #1#2#3 +\cs_new_protected:Npn \__siunitx_number_parse_loop_main_uncert:NN #1#2 { \__siunitx_number_parse_loop_main_store:NNN #1 #2 \c_false_bool - \__siunitx_number_parse_uncert:NN #1 + \tl_clear:N \l__siunitx_number_uncert_tl + \__siunitx_number_parse_uncert:N } \cs_new_protected:Npn \__siunitx_number_parse_loop_main_sign:NNN #1#2#3 { \__siunitx_number_parse_loop_main_store:NNN #1 #2 \c_true_bool + \tl_put_right:NV \l__siunitx_number_uncert_tl \l__siunitx_number_flex_tl \tl_set:Nn \l__siunitx_number_flex_tl { {#3} } \__siunitx_number_parse_loop_first:NNN \l__siunitx_number_flex_tl \c_false_bool } \cs_new_protected:Npn \__siunitx_number_parse_loop_main_store:NNN #1#2#3 { - \tl_if_empty:NT \l__siunitx_number_partial_tl - { \tl_set:Nn \l__siunitx_number_partial_tl { 0 } } \tl_put_right:Nx #1 { - { \exp_not:V \l__siunitx_number_partial_tl } + { + \tl_if_empty:NTF \l__siunitx_number_partial_tl + { 0 } + { \exp_not:V \l__siunitx_number_partial_tl } + } \bool_if:NT #2 { { } } \bool_if:NT #3 { { } } } \tl_clear:N \l__siunitx_number_partial_tl } -\cs_new_protected:Npn \__siunitx_number_parse_loop_after_decimal:NNN #1#2#3 +\cs_new_protected:Npn \__siunitx_number_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 - { \__siunitx_number_parse_loop_break:wN \q_recursion_stop } + \quark_if_recursion_tail_stop_do:Nn #2 + { \__siunitx_number_parse_loop_break:w \q_recursion_stop } \tl_if_in:NnTF \l__siunitx_number_input_digit_tl {#1} { - \tl_put_right:Nn \l__siunitx_number_partial_tl {#3} - \__siunitx_number_parse_loop_main:NNNNN - #1 \c_false_bool \c_true_bool #2 + \tl_put_right:Nn \l__siunitx_number_partial_tl {#2} + \__siunitx_number_parse_loop_main:NNNN + #1 \c_false_bool \c_true_bool } - { \__siunitx_number_parse_loop_break:wN } + { \__siunitx_number_parse_loop_break:w } } { - \__siunitx_number_parse_loop_main:NNNNN - #1 \c_false_bool \c_true_bool #2 #3 + \__siunitx_number_parse_loop_main:NNNN + #1 \c_false_bool \c_true_bool #2 } } -\cs_new_protected:Npn \__siunitx_number_parse_loop_break:wN +\cs_new_protected:Npn \__siunitx_number_parse_loop_break:w #1 \q_recursion_stop { \tl_clear:N \l__siunitx_number_flex_tl @@ -2030,115 +2300,128 @@ { \tl_clear:N \l__siunitx_number_parsed_tl } { \__siunitx_number_parse_exponent: } } -\cs_new_protected:Npn \__siunitx_number_parse_uncert:NN #1#2 +\cs_new_protected:Npn \__siunitx_number_parse_uncert:N #1 { - \quark_if_recursion_tail_stop_do:Nn #2 - { \__siunitx_number_parse_loop_break:wN \q_recursion_stop } - \tl_if_in:NnTF \l__siunitx_number_input_uncert_close_tl {#2} - { \__siunitx_number_parse_loop_break:wN } + \quark_if_recursion_tail_stop_do:Nn #1 + { \__siunitx_number_parse_loop_break:w \q_recursion_stop } + \tl_if_in:NnTF \l__siunitx_number_input_uncert_close_tl {#1} + { \__siunitx_number_parse_loop_break:w } { - \__siunitx_number_parse_uncert:NNNN - #1 \c_false_bool \__siunitx_number_parse_uncert_auxi:NN #2 + \__siunitx_number_parse_uncert:NNN + \c_false_bool \__siunitx_number_parse_uncert_auxi:N #1 } } -\cs_new_protected:Npn \__siunitx_number_parse_uncert:NNNN #1#2#3#4 +\cs_new_protected:Npn \__siunitx_number_parse_uncert:NNN #1#2#3 { - \quark_if_recursion_tail_stop_do:Nn #4 - { \__siunitx_number_parse_loop_break:wN \q_recursion_stop } - \tl_if_in:NnTF \l__siunitx_number_input_digit_tl {#4} + \quark_if_recursion_tail_stop_do:Nn #3 + { \__siunitx_number_parse_loop_break:w \q_recursion_stop } + \tl_if_in:NnTF \l__siunitx_number_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__siunitx_number_partial_tl {#4} - \__siunitx_number_parse_uncert:NNNN #1 \c_true_bool #3 + \tl_put_right:Nn \l__siunitx_number_partial_tl {#3} + \__siunitx_number_parse_uncert:NNN \c_true_bool #2 } - { \__siunitx_number_parse_uncert:NNNN #1 \c_false_bool #3 } + { \__siunitx_number_parse_uncert:NNN \c_false_bool #2 } } - { #3 #1#4 } + { #2 #3 } } -\cs_new_protected:Npn \__siunitx_number_parse_uncert_auxi:NN #1#2 +\cs_new_protected:Npn \__siunitx_number_parse_uncert_auxi:N #1 { - \tl_if_in:NnTF \l__siunitx_number_input_uncert_close_tl {#2} + \tl_if_in:NnTF \l__siunitx_number_input_uncert_close_tl {#1} { - \__siunitx_number_parse_uncert_auxiii:N #1 + \__siunitx_number_parse_uncert_auxiii: \__siunitx_number_parse_uncert_after:N } { - \tl_if_in:NnTF \l_siunitx_number_input_decimal_tl {#2} - { \__siunitx_number_parse_uncert_marker:N #1 } - { \__siunitx_number_parse_loop_break:wN } + \tl_if_in:NnTF \l_siunitx_number_input_decimal_tl {#1} + { \__siunitx_number_parse_uncert_marker: } + { \__siunitx_number_parse_loop_break:w } } } -\cs_new_protected:Npn \__siunitx_number_parse_uncert_auxii:NN #1#2 +\cs_new_protected:Npn \__siunitx_number_parse_uncert_auxii:N #1 { - \tl_if_in:NnTF \l__siunitx_number_input_uncert_close_tl {#2} + \tl_if_in:NnTF \l__siunitx_number_input_uncert_close_tl {#1} { - \__siunitx_number_parse_uncert_auxiii:N #1 + \__siunitx_number_parse_uncert_auxiii: \__siunitx_number_parse_uncert_after:N } - { \__siunitx_number_parse_loop_break:wN } + { \__siunitx_number_parse_loop_break:w } } -\cs_new_protected:Npn \__siunitx_number_parse_uncert_auxiii:N #1 +\cs_new_protected:Npn \__siunitx_number_parse_uncert_auxiii: { - \tl_if_empty:NTF \l__siunitx_number_partial_tl - { - \tl_put_right:Nx #1 - { - { - \bool_if:NT \l__siunitx_number_zero_uncert_bool - { { S } { 0 } } - } - } - } - { - \tl_set:Nx \l__siunitx_number_partial_tl - { { S } { \exp_not:V \l__siunitx_number_partial_tl } } - \__siunitx_number_parse_loop_main_store:NNN #1 - \c_false_bool \c_false_bool - } + \bool_lazy_and:nnT + { \l__siunitx_number_zero_uncert_bool } + { \tl_if_empty_p:N \l__siunitx_number_partial_tl } + { \tl_set:Nn \l__siunitx_number_partial_tl { 0 } } + } +\cs_new_protected:Npn \__siunitx_number_parse_uncert_marker: + { + \exp_after:wN \__siunitx_number_parse_uncert_marker:nnn + \l__siunitx_number_parsed_tl } -\cs_new_protected:Npn \__siunitx_number_parse_uncert_marker:N #1 - { \exp_after:wN \__siunitx_number_parse_uncert_marker:nnnN #1 #1 } -\cs_new_protected:Npn \__siunitx_number_parse_uncert_marker:nnnN #1#2#3#4 +\cs_new_protected:Npn \__siunitx_number_parse_uncert_marker:nnn #1#2#3 { \int_compare:nNnTF { \tl_count:N \l__siunitx_number_partial_tl } > { \tl_count:n {#2} } - { \__siunitx_number_parse_loop_break:wN } - { \__siunitx_number_parse_uncert_marker:nNw {#3} #4 } + { \__siunitx_number_parse_loop_break:w } + { \__siunitx_number_parse_uncert_marker:nw {#3} } } -\cs_new_protected:Npn \__siunitx_number_parse_uncert_marker:nNw - #1#2#3 \q_recursion_tail \q_recursion_stop +\cs_new_protected:Npn \__siunitx_number_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__siunitx_number_partial_tl } + { \exp_not:V \l__siunitx_number_uncert_tl } { \prg_replicate:nn { \tl_count:N \l__siunitx_number_partial_tl } { 0 } } - { - \__siunitx_number_parse_uncert:NNNN - #2 \c_false_bool - } - { - \__siunitx_number_parse_uncert:NNNN - #2 \c_true_bool - } - \__siunitx_number_parse_uncert_auxii:NN + { \__siunitx_number_parse_uncert:NNN \c_false_bool } + { \__siunitx_number_parse_uncert:NNN \c_true_bool } + \__siunitx_number_parse_uncert_auxii:N } - { \exp_after:wN \__siunitx_number_parse_uncert_extend:nnnN #2 #2 } - #3 \q_recursion_tail \q_recursion_stop + { \exp_after:wN \__siunitx_number_parse_uncert_extend:nnn \l__siunitx_number_parsed_tl } + #2 \q_recursion_tail \q_recursion_stop } -\cs_new_protected:Npn \__siunitx_number_parse_uncert_extend:nnnN #1#2#3#4 +\cs_new_protected:Npn \__siunitx_number_parse_uncert_extend:nnn #1#2#3 { - \tl_set:Nn #4 { {#1} {#2} { #3 0 } } - \__siunitx_number_parse_uncert:NNNN #4 \c_true_bool - \__siunitx_number_parse_uncert_auxii:NN + \tl_set:Nn \l__siunitx_number_parsed_tl { {#1} {#2} { #3 0 } } + \__siunitx_number_parse_uncert:NNN \c_true_bool + \__siunitx_number_parse_uncert_auxii:N } \cs_new_protected:Npn \__siunitx_number_parse_uncert_after:N #1 { - \quark_if_recursion_tail_stop:N #1 - \__siunitx_number_parse_loop_break:wN + \tl_set:Nx \l__siunitx_number_uncert_tl + { + \exp_not:V \l__siunitx_number_uncert_tl + \tl_if_empty:NF \l__siunitx_number_partial_tl + { { \exp_not:V \l__siunitx_number_partial_tl } } + } + \tl_clear:N \l__siunitx_number_partial_tl + \quark_if_recursion_tail_stop_do:Nn #1 + { + \tl_set:Nx \l__siunitx_number_parsed_tl + { + \exp_not:V \l__siunitx_number_parsed_tl + { + \tl_if_empty:NF \l__siunitx_number_uncert_tl + { + { + \prg_replicate:nn + { \tl_count:N \l__siunitx_number_uncert_tl } + { S } + } + \exp_not:V \l__siunitx_number_uncert_tl + } + } + } + \tl_clear:N \l__siunitx_number_partial_tl + \tl_clear:N \l__siunitx_number_uncert_tl + } + \tl_if_in:NnTF \l__siunitx_number_input_uncert_open_tl {#1} + { \__siunitx_number_parse_uncert:N } + { \__siunitx_number_parse_loop_break:w } } \keys_define:nn { siunitx } { @@ -2171,6 +2454,8 @@ \l__siunitx_number_round_pad_bool , round-precision .int_set:N = \l__siunitx_number_round_precision_int , + round-zero-positive .bool_set:N = + \l__siunitx_number_round_positive_bool } \bool_new:N \l__siunitx_number_round_half_even_bool \tl_new:N \l__siunitx_number_exponent_mode_tl @@ -2485,7 +2770,10 @@ \exp_not:n {#4} \__siunitx_number_digits:nn \l__siunitx_number_min_decimal_int {#4} } - { \tl_if_blank:nF {#5} { \__siunitx_number_digits_uncert:nnn {#4} #5 } } + { + \tl_if_blank:nF {#5} + { \__siunitx_number_digits_uncert:nnw {#4} #5 \q_stop } + } \exp_not:n { {#6} {#7} } } \cs_new:Npn \__siunitx_number_digits:nn #1#2 @@ -2494,12 +2782,26 @@ { #1 - \tl_count:n {#2} } > 0 { \prg_replicate:nn { #1 - \tl_count:n {#2} } { 0 } } } -\cs_new:Npn \__siunitx_number_digits_uncert:nnn #1#2#3 +\cs_new:Npn \__siunitx_number_digits_uncert:nnw #1#2#3 \q_stop { { #2 } - { \use:c { __siunitx_number_digits_uncert_ #2 :nn } {#1} {#3} } + \cs_if_exist:cTF { __siunitx_number_digits_uncert_ #2 :nn } + { { \use:c { __siunitx_number_digits_uncert_ #2 :nn } {#1} {#3} } } + { + \__siunitx_number_digits_uncert:nN {#1} #2 \q_recursion_tail + #3 \q_recursion_stop + } + } +\cs_new:Npn \__siunitx_number_digits_uncert_A:nn #1#2 + { \__siunitx_number_digits_uncert_A:nnn {#1} #2 } +\cs_new:Npn \__siunitx_number_digits_uncert_A:nnn #1#2#3 + { + { \__siunitx_number_digits_uncert_aux:nn {#1} {#2} } + { \__siunitx_number_digits_uncert_aux:nn {#1} {#3} } } \cs_new:Npn \__siunitx_number_digits_uncert_S:nn #1#2 + { \__siunitx_number_digits_uncert_aux:nn {#1} {#2} } +\cs_new:Npn \__siunitx_number_digits_uncert_aux:nn #1#2 { \exp_not:n {#2} \__siunitx_number_digits:nn @@ -2510,6 +2812,16 @@ } {#2} } +\cs_new:Npn \__siunitx_number_digits_uncert:nN #1#2 + { + \quark_if_recursion_tail_stop:N #2 + \__siunitx_number_digits_uncert:nNw {#1} #2 + } +\cs_new:Npn \__siunitx_number_digits_uncert:nNw #1#2#3 \q_recursion_tail #4 + { + { \use:c { __siunitx_number_digits_uncert_ #2 :nn } {#1} {#4} } + \__siunitx_number_digits_uncert:nN {#1} #3 \q_recursion_tail + } \cs_new_protected:Npn \__siunitx_number_drop_exponent:NN #1#2 { \bool_if:NT \l__siunitx_number_drop_exponent_bool @@ -2935,17 +3247,19 @@ { \__siunitx_number_round_places_finalise:nnnnnnn #1 } \cs_new:Npn \__siunitx_number_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__siunitx_number_round_min_tl { \exp_not:n { {#1} } - { \str_if_eq:nnF {#2} { - } { \exp_not:n {#2} } } + { + \bool_lazy_and:nnF + { \l__siunitx_number_round_positive_bool } + { \str_if_eq_p:nn {#2} { - } } + { \exp_not:n {#2} } + } \exp_not:n { {#3} {#4} {#5} {#6} {#7} } } { @@ -3167,6 +3481,15 @@ \l__siunitx_number_exponent_base_tl , exponent-product .tl_set:N = \l__siunitx_number_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__siunitx_number_group_first_int , + digit-group-other-size .int_set:N = + \l__siunitx_number_group_size_int , group-digits .choice: , group-digits / all .code:n = { @@ -3213,14 +3536,25 @@ \l__siunitx_number_zero_integer_bool , tight-spacing .bool_set:N = \l__siunitx_number_tight_bool , + uncertainty-descriptor-mode .choices:nn = + { bracket , bracket-separator , separator , subscript } + { \tl_set_eq:NN \l__siunitx_number_uncert_desc_mode_tl \l_keys_choice_tl } , + uncertainty-descriptor-separator .tl_set:N = + \l__siunitx_number_uncert_desc_separator_tl , + uncertainty-descriptors .clist_set:N = + \l__siunitx_number_uncert_desc_clist , uncertainty-mode .choices:nn = { compact , compact-marker , full , separate } { \tl_set_eq:NN \l__siunitx_number_uncert_mode_tl \l_keys_choice_tl } , uncertainty-separator .tl_set:N = - \l__siunitx_number_uncert_separator_tl + \l__siunitx_number_uncert_separator_tl , + zero-decimal-as-symbol .bool_set:N = + \l__siunitx_number_zero_symbol_bool , + zero-symbol .tl_set:N = \l__siunitx_number_zero_symbol_tl } \bool_new:N \l__siunitx_number_group_decimal_bool \bool_new:N \l__siunitx_number_group_integer_bool +\tl_new:N \l__siunitx_number_uncert_desc_mode_tl \tl_new:N \l__siunitx_number_uncert_mode_tl \cs_new:Npn \siunitx_number_output:N #1 { \__siunitx_number_output:Nn #1 { } } @@ -3365,7 +3699,17 @@ } \exp_not:n {#2} \str_if_eq:nnF {#1} { \empty } - { \__siunitx_number_output_digits:nn { decimal } {#1} } + { + \bool_lazy_and:nnTF + { \l__siunitx_number_zero_symbol_bool } + { + \str_if_eq_p:ee + {#1} + { \prg_replicate:nn { \tl_count:n {#1} } { 0 } } + } + { \exp_not:V \l__siunitx_number_zero_symbol_tl } + { \__siunitx_number_output_digits:nn { decimal } {#1} } + } } \cs_generate_variant:Nn \__siunitx_number_output_decimal:nn { f } \cs_new:Npn \__siunitx_number_output_digits:nn #1#2 @@ -3375,11 +3719,29 @@ \int_compare:nNnTF { \tl_count:n {#2} } < \l__siunitx_number_group_minimum_int { \exp_not:n {#2} } - { \use:c { __siunitx_number_output_ #1 _aux:n } {#2} } + { + \cs_if_exist_use:cF + { + __siunitx_number_output_ #1 _ + \int_use:N \l__siunitx_number_group_first_int + _ + \int_use:N \l__siunitx_number_group_size_int + :n + } + { \use:c { __siunitx_number_output_ #1 _first:n } } + {#2} + } } { \exp_not:n {#2} } } -\cs_new:Npn \__siunitx_number_output_integer_aux:n #1 +\cs_new:Npn \__siunitx_number_output_digit_separator:N #1 + { + \str_if_eq:VnTF #1 { , } + { \exp_not:N \mathord } + { \use:n } + { \exp_not:V #1 } + } +\cs_new:cpn { __siunitx_number_output_integer_3_3:n } #1 { \use:c { @@ -3402,15 +3764,39 @@ } \cs_new:Npn \__siunitx_number_output_integer_loop:NNNN #1#2#3#4 { - \str_if_eq:VnTF \l__siunitx_number_group_separator_tl { , } - { \exp_not:N \mathord } - { \use:n } - { \exp_not:V \l__siunitx_number_group_separator_tl } + \__siunitx_number_output_digit_separator:N \l__siunitx_number_group_separator_tl \exp_not:n {#1#2#3} \quark_if_nil:NF #4 { \__siunitx_number_output_integer_loop:NNNN #4 } } -\cs_new:Npn \__siunitx_number_output_decimal_aux:n #1 +\cs_new:Npn \__siunitx_number_output_integer_first:n #1 + { + \exp_args:Ne \__siunitx_number_output_integer_aux:n { \tl_reverse:n {#1} } + } +\cs_new:Npn \__siunitx_number_output_integer_aux:n #1 + { + \__siunitx_number_output_integer_loop:NnnN \l__siunitx_number_group_first_int { 0 } { } + #1 \q_recursion_tail \q_recursion_stop + } +\cs_new:Npn \__siunitx_number_output_integer_loop:NnnN #1#2#3#4 + { + \quark_if_recursion_tail_stop_do:Nn #4 {#3} + \int_compare:nNnTF { #2 + 1 } > #1 + { + \__siunitx_number_output_integer_loop:NnnN + \l__siunitx_number_group_size_int { 1 } + { + \exp_not:n {#4} + \__siunitx_number_output_digit_separator:N \l__siunitx_number_group_separator_tl + #3 + } + } + { + \__siunitx_number_output_integer_loop:NnnN #1 { #2 + 1 } + { \exp_not:n {#4} #3 } + } + } +\cs_new:cpn { __siunitx_number_output_decimal_3_3:n } #1 { \__siunitx_number_output_decimal_loop:NNNN \c_empty_tl #1 \q_nil \q_nil \q_nil @@ -3419,7 +3805,7 @@ { \quark_if_nil:NF #2 { - \exp_not:V #1 + \__siunitx_number_output_digit_separator:N #1 \exp_not:n {#2} \quark_if_nil:NTF #3 { \use_none:n } @@ -3435,31 +3821,154 @@ } } } +\cs_new:cpn { __siunitx_number_output_decimal_3_2:n } #1 + { + \int_compare:nNnTF { \tl_count:n {#1} } > 2 + { \__siunitx_number_output_decimal:NNNw #1 \q_stop } + { \exp_not:n {#1} } + } +\cs_new:Npn \__siunitx_number_output_decimal:NNNw #1#2#3#4 \q_stop + { + \exp_not:n {#1#2#3} + \__siunitx_number_output_decimal_loop:NN #4 \q_nil \q_nil + } +\cs_new:Npn \__siunitx_number_output_decimal_loop:NN #1#2 + { + \quark_if_nil:NF #1 + { + \__siunitx_number_output_digit_separator:N + \l__siunitx_number_group_separator_tl + \exp_not:n {#1} + \quark_if_nil:NTF #2 + { \use_none:n } + { + \exp_not:n {#2} + \__siunitx_number_output_decimal_loop:NN + } + } + } +\cs_new:Npn \__siunitx_number_output_decimal_first:n #1 + { + \__siunitx_number_output_decimal_loop:NnnN \l__siunitx_number_group_first_int { 0 } { } + #1 \q_recursion_tail \q_recursion_stop + } +\cs_new:Npn \__siunitx_number_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} + \__siunitx_number_output_digit_separator:N + \l__siunitx_number_group_separator_tl + \__siunitx_number_output_decimal_loop:NnnN \l__siunitx_number_group_size_int { 1 } {#4} + } + { \__siunitx_number_output_decimal_loop:NnnN #1 { #2 + 1 } { #3 #4 } } + } \cs_new:Npn \__siunitx_number_output_uncertainty:nnn #1#2#3 { \tl_if_blank:nTF {#1} { \__siunitx_number_output_uncertainty_unaligned:n {#3} } { - \use:c { __siunitx_number_output_uncert_ \tl_head:n {#1} :nnnw } - {#2} {#3} #1 + \cs_if_exist:cTF + { __siunitx_number_output_uncert_ \tl_head:n {#1} :nnnn } + { + \use:c { __siunitx_number_output_uncert_ \tl_head:n {#1} :nnnn } + {#2} {#3} #1 + } + { \__siunitx_number_output_uncert:nnnn {#2} {#3} #1 } } } \cs_new:Npn \__siunitx_number_output_uncertainty_unaligned:n #1 { \exp_not:n { #1 #1 #1 #1 } } -\cs_new:Npn \__siunitx_number_output_uncert_S:nnnw #1#2#3#4 +\cs_new:Npn \__siunitx_number_output_uncert:nnnn #1#2#3#4 { - \str_if_eq:VnTF \l__siunitx_number_uncert_mode_tl { separate } + \exp_args:NV \__siunitx_number_output_uncert:nnnnn \l__siunitx_number_uncert_desc_clist + {#1} {#2} {#3} {#4} + } +\cs_new:Npn \__siunitx_number_output_uncert:nnnnn #1#2#3#4#5 + { + \__siunitx_number_output_uncert_loop:nnN {#2} {#3} + #4 \q_recursion_tail #1 , \q_recursion_stop {#5} + } +\cs_new:Npn \__siunitx_number_output_uncert_loop:nnN #1#2#3 + { + \quark_if_recursion_tail_stop:N #3 + \__siunitx_number_output_uncert_loop:nnNw {#1} {#2} #3 + } +\cs_new:Npn \__siunitx_number_output_uncert_loop:nnNw + #1#2#3#4 \q_recursion_tail #5 , #6 \q_recursion_stop #7 + { + \use:c { __siunitx_number_output_uncert_ #3 _loop:nnn } {#1} {#2} {#7} + \tl_if_blank:nF {#5} + { \use:c { __siunitx_number_output_uncert_desc_ \l__siunitx_number_uncert_desc_mode_tl :n } {#5} } + \__siunitx_number_output_uncert_loop:nnN {#1} {#2} #4 + \q_recursion_tail #6 , \q_recursion_stop + } +\cs_new:Npn \__siunitx_number_output_uncert_desc_bracket:n #1 + { + \exp_not:V \l__siunitx_number_bracket_open_tl + \exp_not:V \l_siunitx_unit_font_tl + { \exp_not:n {#1} } + \exp_not:V \l__siunitx_number_bracket_close_tl + } +\cs_new:cpn { __siunitx_number_output_uncert_desc_bracket-separator:n } #1 + { + \exp_not:V \l__siunitx_number_uncert_desc_separator_tl + \exp_not:V \l__siunitx_number_bracket_open_tl + \exp_not:V \l_siunitx_unit_font_tl + { \exp_not:n {#1} } + \exp_not:V \l__siunitx_number_bracket_close_tl + } +\cs_new:Npn \__siunitx_number_output_uncert_desc_separator:n #1 + { + \exp_not:V \l__siunitx_number_uncert_desc_separator_tl + \exp_not:V \l_siunitx_unit_font_tl + { \exp_not:n {#1} } + } +\cs_new:Npx \__siunitx_number_output_uncert_desc_subscript:n #1 + { + \char_generate:nn { `\_ } { 8 } { - \exp_not:n {#2} - \bool_if:NTF \l__siunitx_number_tight_bool - { \mathord } - { \use:n } - { \exp_not:n { \pm } } - \exp_not:n {#2} - \__siunitx_number_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} } + } + } +\cs_new:Npn \__siunitx_number_output_uncert_A_loop:nnn #1#2#3 + { \__siunitx_number_output_uncert_A_multi:nnnn {#1} {#2} { A } {#3} } +\cs_new:Npn \__siunitx_number_output_uncert_S_loop:nnn #1#2#3 + { + \__siunitx_number_output_uncert_S_multi:nnnn {#1} {#2} { S } {#3} + \__siunitx_number_output_uncert_S_loop:w + } +\cs_new:Npn \__siunitx_number_output_uncert_S_loop:w #1 \__siunitx_number_output_uncert_loop:nnN #2#3 + { + #1 + \__siunitx_number_output_uncert_loop:nnN {#2} { } + } +\cs_new:Npn \__siunitx_number_output_uncert_A:nnnn #1#2#3#4 + { \__siunitx_number_output_uncert_A:nnnnn {#1} {#2} {#3} #4 } +\cs_new_eq:NN \__siunitx_number_output_uncert_A_multi:nnnn + \__siunitx_number_output_uncert_A:nnnn +\cs_new:Npx \__siunitx_number_output_uncert_A:nnnnn #1#2#3#4#5 + { + ^ + { + + + \exp_not:N \__siunitx_number_output_uncert_augment:nnnn + {#4} {#1} {#4} {#2} } + \char_generate:nn { `\_ } { 8 } + { + - + \exp_not:N \__siunitx_number_output_uncert_augment:nnnn + {#5} {#1} {#5} {#2} + } + \exp_not:N \__siunitx_number_output_uncertainty_unaligned:n {#2} + } +\cs_new:Npn \__siunitx_number_output_uncert_S:nnnn #1#2#3#4 + { + \str_if_eq:VnTF \l__siunitx_number_uncert_mode_tl { separate } + { \__siunitx_number_output_uncert_S_sep:nnnn {#1} {#2} {#3} {#4} } { \exp_not:V \l__siunitx_number_uncert_separator_tl \exp_not:V \l__siunitx_number_output_uncert_open_tl @@ -3468,11 +3977,44 @@ \__siunitx_number_output_uncertainty_unaligned:n {#2} } } -\cs_new:Npn \__siunitx_number_output_uncert_S_aux:nnn #1#2#3 +\cs_new:Npn \__siunitx_number_output_uncert_S_sep:nnnn #1#2#3#4 + { + \exp_not:n {#2} + \bool_if:NTF \l__siunitx_number_tight_bool + { \mathord } + { \use:n } + { \exp_not:n { \pm } } + \exp_not:n {#2} + \__siunitx_number_output_uncert_augment:nnnn {#4} {#1} {#4} {#2} + } +\cs_new_eq:NN \__siunitx_number_output_uncert_S_multi:nnnn + \__siunitx_number_output_uncert_S_sep:nnnn +\cs_new:Npn \__siunitx_number_output_uncert_S_compact:nn #1#2 + { \exp_not:n {#2} } +\cs_new:cpn { __siunitx_number_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} } } + { \__siunitx_number_output_uncert_S_compact:nn } + { \__siunitx_number_output_uncert_S_full:nn } + {#1} {#2} + } +\cs_new:Npn \__siunitx_number_output_uncert_S_full:nn #1#2 + { + \__siunitx_number_output_uncert_augment:nnnn {#2} {#1} {#2} { } + } +\cs_new:Npn \__siunitx_number_output_uncert_augment:nnnn #1#2#3#4 + { + \exp_args:Nf \__siunitx_number_output_uncert_augment:nnn + { \int_eval:n { \tl_count:n {#1} - \tl_count:n {#2} } } + {#3} {#4} + } +\cs_new:Npn \__siunitx_number_output_uncert_augment:nnn #1#2#3 { \int_compare:nNnTF {#1} > 0 { - \__siunitx_number_output_uncert_S_aux:fnnw + \__siunitx_number_output_uncert_augment:fnnw { \int_eval:n { #1 - 1 } } {#3} { } @@ -3488,44 +4030,26 @@ {#3} } } -\cs_generate_variant:Nn \__siunitx_number_output_uncert_S_aux:nnn { f } -\cs_new:Npn \__siunitx_number_output_uncert_S_aux:nnnw #1#2#3#4 +\cs_new:Npn \__siunitx_number_output_uncert_augment:nnnw #1#2#3#4 { \quark_if_nil:NF #4 { \int_compare:nNnTF {#1} = 0 - { \__siunitx_number_output_uncert_S_aux:nnw {#3#4} {#2} } + { \__siunitx_number_output_uncert_augment:nnw {#3#4} {#2} } { - \__siunitx_number_output_uncert_S_aux:fnnw + \__siunitx_number_output_uncert_augment:fnnw { \int_eval:n { #1 - 1 } } {#2} {#3#4} } } } -\cs_generate_variant:Nn \__siunitx_number_output_uncert_S_aux:nnnw { f } -\cs_new:Npn \__siunitx_number_output_uncert_S_aux:nnw #1#2#3 \q_nil +\cs_generate_variant:Nn \__siunitx_number_output_uncert_augment:nnnw { f } +\cs_new:Npn \__siunitx_number_output_uncert_augment:nnw #1#2#3 \q_nil { \__siunitx_number_output_digits:nn { integer } {#1} \__siunitx_number_output_decimal:nn {#3} {#2} } -\cs_new:Npn \__siunitx_number_output_uncert_S_compact:nn #1#2 - { \exp_not:n {#2} } -\cs_new:cpn { __siunitx_number_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} } } - { \__siunitx_number_output_uncert_S_compact:nn } - { \__siunitx_number_output_uncert_S_full:nn } - {#1} {#2} - } -\cs_new:Npn \__siunitx_number_output_uncert_S_full:nn #1#2 - { - \__siunitx_number_output_uncert_S_aux:fnn - { \int_eval:n { \tl_count:n {#2} - \tl_count:n {#1} } } - {#2} { } - } \cs_new:Npn \__siunitx_number_output_exponent:nnnnn #1#2#3#4#5 { \exp_not:n {#5} @@ -3655,51 +4179,61 @@ } \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 { --- } } \RequirePackage { amstext } \cs_new_eq:NN \__siunitx_print_ams_text:n \text @@ -3736,6 +4270,10 @@ \l__siunitx_print_math_family_bool , text-font-command .tl_set:N = \l__siunitx_print_text_font_tl , + text-subscript-command .tl_set:N = + \l__siunitx_print_text_sub_tl , + text-superscript-command .tl_set:N = + \l__siunitx_print_text_super_tl , text-series-to-math .bool_set:N = \l__siunitx_print_math_series_bool , unit-color .tl_set:N = @@ -4008,18 +4546,29 @@ \tl_set:Nn \l__siunitx_print_tmp_tl {#1} \tl_if_empty:NF \l__siunitx_print_tmp_tl { - \tl_if_empty:NF \l_siunitx_unit_font_tl - { \exp_after:wN \cs_set_eq:NN \l_siunitx_unit_font_tl \use:n } - \cs_set:Npn \mathord ##1 - { \__siunitx_print_text_replace_first:N ##1 } - \cs_set:Npn \pm { \: \exp_not:N \textpm \: } - \tl_map_inline:nn - { \mp \ge \le \gg \ll } - { \cs_set:Npn ##1 { \exp_not:N \ensuremath { \exp_not:N ##1 } } } - \cs_set:Npn \cdot { \: \exp_not:N \textperiodcentered \: } - \cs_set:Npn \times { \: \exp_not:N \texttimes \: } - \protected@edef \l__siunitx_print_tmp_tl - { \exp_after:wN \__siunitx_print_text_replace_first:N \l__siunitx_print_tmp_tl } + \tl_if_empty:NF \l_siunitx_unit_font_tl + { \exp_after:wN \cs_set_eq:NN \l_siunitx_unit_font_tl \use:n } + \cs_set:Npn \mathord ##1 + { \__siunitx_print_text_replace_first:N ##1 } + \group_begin: + \cs_set:Npn \pm { \: \exp_not:N \textpm \: } + \tl_map_inline:nn + { \mp \ge \le \gg \ll \angle } + { + \cs_set:Npn ##1 + { \exp_not:N \ensuremath { \exp_not:N ##1 } } + } + \cs_set:Npn \cdot { \: \exp_not:N \textperiodcentered \: } + \cs_set:Npn \sqrt ##1 + { + \exp_not:N \ensuremath + { \exp_not:N \sqrt { \exp_not:N \text {##1} } } + } + \cs_set:Npn \times { \: \exp_not:N \texttimes \: } + \protected@edef \l__siunitx_print_tmp_tl + { \exp_after:wN \__siunitx_print_text_replace_first:N \l__siunitx_print_tmp_tl } + \exp_args:NNNV \group_end: + \tl_set:Nn \l__siunitx_print_tmp_tl \l__siunitx_print_tmp_tl \__siunitx_print_text_replace:N \l__siunitx_print_tmp_tl \__siunitx_print_text_replace_aux:n { \tl_use:N \l__siunitx_print_tmp_tl } } @@ -4086,15 +4635,15 @@ } \cs_new_protected:Npn \__siunitx_print_text_sub:n #1 { - \__siunitx_print_text_scripts:NnN - \textsubscript {#1} \__siunitx_print_text_super:n + \__siunitx_print_text_scripts:VnN + \l__siunitx_print_text_sub_tl {#1} \__siunitx_print_text_super:n } \cs_new_protected:Npn \__siunitx_print_text_super:n #1 { - \__siunitx_print_text_scripts:NnN - \textsuperscript {#1} \__siunitx_print_text_sub:n + \__siunitx_print_text_scripts:VnN + \l__siunitx_print_text_super_tl {#1} \__siunitx_print_text_sub:n } -\cs_new_protected:Npn \__siunitx_print_text_scripts:NnN #1#2#3 +\cs_new_protected:Npn \__siunitx_print_text_scripts:nnN #1#2#3 { \cs_set_protected:Npn \__siunitx_print_text_scripts: { @@ -4107,6 +4656,7 @@ } \peek_after:Nw \__siunitx_print_text_scripts: } +\cs_generate_variant:Nn \__siunitx_print_text_scripts:nnN { V } \cs_new_protected:Npn \__siunitx_print_text_scripts: { } \cs_new_protected:Npn \__siunitx_print_text_scripts_one:Nn #1#2 { @@ -4153,20 +4703,22 @@ } \keys_set:nn { siunitx } { - color = , - mode = math , - number-color = , - number-mode = math , - propagate-math-font = false , - reset-math-version = true , - reset-text-shape = true , - reset-text-series = true , - reset-text-family = true , - text-family-to-math = false , - text-font-command = , - text-series-to-math = false , - unit-color = , - unit-mode = math + color = , + mode = math , + number-color = , + number-mode = math , + propagate-math-font = false , + reset-math-version = true , + reset-text-shape = true , + reset-text-series = true , + reset-text-family = true , + text-family-to-math = false , + text-font-command = , + text-subscript-command = \textsubscript , + text-superscript-command = \textsuperscript , + text-series-to-math = false , + unit-color = , + unit-mode = math } \keys_set:nn { siunitx / series-version-mapping } { @@ -5054,6 +5606,7 @@ table-alignment-mode = marker } \cs_generate_variant:Nn \tl_replace_all:Nnn { NnV } +\bool_new:N \l__siunitx_unit_tmp_bool \fp_new:N \l__siunitx_unit_tmp_fp \int_new:N \l__siunitx_unit_tmp_int \tl_new:N \l__siunitx_unit_tmp_tl @@ -5243,7 +5796,7 @@ } { \bool_if:NTF \l__siunitx_unit_forbid_literal_bool - { \msg_error:nnn { siunitx } { unit / literal } {#1} } + { \msg_error:nnn { siunitx } { literal-unit } {#1} } { \__siunitx_unit_format_literal:n {#1} } } } @@ -5429,7 +5982,7 @@ \prop_if_in:NVTF \l__siunitx_unit_parsed_prop \l__siunitx_unit_tmp_tl { - \msg_error:nnxx { siunitx } { unit / duplicate-part } + \msg_error:nnxx { siunitx } { duplicate-part } { \exp_not:n {#1} } { \token_to_str:N #3 } } { @@ -5463,7 +6016,7 @@ } { \msg_error:nnxx { siunitx } - { unit / part-before-unit } { power } { \token_to_str:N #1 } + { part-before-unit } { power } { \token_to_str:N #1 } } } \cs_new_protected:Npn \__siunitx_unit_parse_qualifier:nn #1#2 @@ -5477,7 +6030,7 @@ } { \msg_error:nnnn { siunitx } - { unit / part-before-unit } { qualifier } { \token_to_str:N #1 } + { part-before-unit } { qualifier } { \token_to_str:N #1 } } } \cs_new_protected:Npn \__siunitx_unit_parse_special:n #1 @@ -5511,7 +6064,7 @@ { \bool_set_true:N \l__siunitx_unit_per_bool \cs_set_protected:Npn \per - { \msg_error:nn { siunitx } { unit / duplicate-sticky-per } } + { \msg_error:nn { siunitx } { duplicate-sticky-per } } } { \__siunitx_unit_parse_add:nnnn @@ -5557,64 +6110,47 @@ \tl_set:Nx \l__siunitx_unit_tmp_tl { ##1 - \int_eval:n { \l__siunitx_unit_position_int + 1 } } \prop_if_in:NVT \l__siunitx_unit_parsed_prop \l__siunitx_unit_tmp_tl - { \msg_error:nnn { siunitx } { unit / dangling-part } { ##1 } } + { \msg_error:nnn { siunitx } { dangling-part } { ##1 } } } } \keys_define:nn { siunitx } { bracket-unit-denominator .bool_set:N = \l__siunitx_unit_denominator_bracket_bool , + display-per-mode .choices:nn = + { + fraction , + power , + power-positive-first , + repeated-symbol , + symbol , + single-symbol + } + { \str_set:Nn \l__siunitx_unit_per_display_str {#1} } , forbid-literal-units .bool_set:N = \l__siunitx_unit_forbid_literal_bool , fraction-command .tl_set:N = \l_siunitx_unit_fraction_tl , parse-units .bool_set:N = \l__siunitx_unit_parse_bool , - per-mode .choice: , - per-mode / fraction .code:n = - { - \bool_set_false:N \l__siunitx_unit_autofrac_bool - \bool_set_false:N \l__siunitx_unit_per_symbol_bool - \bool_set_true:N \l__siunitx_unit_powers_positive_bool - \bool_set_true:N \l__siunitx_unit_two_part_bool - } , - per-mode / power .code:n = - { - \bool_set_false:N \l__siunitx_unit_autofrac_bool - \bool_set_false:N \l__siunitx_unit_per_symbol_bool - \bool_set_false:N \l__siunitx_unit_powers_positive_bool - \bool_set_false:N \l__siunitx_unit_two_part_bool - } , - per-mode / power-positive-first .code:n = - { - \bool_set_false:N \l__siunitx_unit_autofrac_bool - \bool_set_false:N \l__siunitx_unit_per_symbol_bool - \bool_set_false:N \l__siunitx_unit_powers_positive_bool - \bool_set_true:N \l__siunitx_unit_two_part_bool - } , - per-mode / repeated-symbol .code:n = - { - \bool_set_false:N \l__siunitx_unit_autofrac_bool - \bool_set_true:N \l__siunitx_unit_per_symbol_bool - \bool_set_true:N \l__siunitx_unit_powers_positive_bool - \bool_set_false:N \l__siunitx_unit_two_part_bool - } , - per-mode / symbol .code:n = - { - \bool_set_false:N \l__siunitx_unit_autofrac_bool - \bool_set_true:N \l__siunitx_unit_per_symbol_bool - \bool_set_true:N \l__siunitx_unit_powers_positive_bool - \bool_set_true:N \l__siunitx_unit_two_part_bool - } , - per-mode / symbol-or-fraction .code:n = - { - \bool_set_true:N \l__siunitx_unit_autofrac_bool - \bool_set_true:N \l__siunitx_unit_per_symbol_bool - \bool_set_true:N \l__siunitx_unit_powers_positive_bool - \bool_set_true:N \l__siunitx_unit_two_part_bool - } , + inline-per-mode .choices:nn = + { + fraction , + power , + power-positive-first , + repeated-symbol , + symbol , + single-symbol + } + { \str_set:Nn \l__siunitx_unit_per_inline_str {#1} } , + per-mode .meta:n = + { display-per-mode = {#1} , inline-per-mode = {#1} } , per-symbol .tl_set:N = \l__siunitx_unit_per_symbol_tl , + per-symbol-script-correction .tl_set:N = + \l__siunitx_unit_per_script_tl , + power-half-as-sqrt .bool_set:N = + \l__siunitx_unit_half_sqrt_bool , qualifier-mode .choices:nn = { bracket , combine , phrase , subscript } { \tl_set_eq:NN \l__siunitx_unit_qualifier_mode_tl \l_keys_choice_tl } , @@ -5627,7 +6163,8 @@ \tl_set:Nn \l__siunitx_unit_bracket_open_tl { ( } \tl_set:Nn \l__siunitx_unit_bracket_close_tl { ) } \bool_new:N \l__siunitx_unit_font_bool -\bool_new:N \l__siunitx_unit_autofrac_bool +\str_new:N \l__siunitx_unit_per_display_str +\str_new:N \l__siunitx_unit_per_inline_str \bool_new:N \l__siunitx_unit_per_symbol_bool \bool_new:N \l__siunitx_unit_powers_positive_bool \bool_new:N \l__siunitx_unit_two_part_bool @@ -5637,13 +6174,41 @@ \bool_new:N \l__siunitx_unit_prefix_exp_bool \fp_new:N \l__siunitx_unit_prefix_fp \fp_new:N \l__siunitx_unit_multiple_fp +\bool_new:N \l__siunitx_unit_current_script_bool +\bool_new:N \l__siunitx_unit_script_bool \tl_new:N \l__siunitx_unit_current_tl \tl_new:N \l__siunitx_unit_part_tl \tl_new:N \l__siunitx_unit_denominator_tl \int_new:N \l__siunitx_unit_total_int \cs_new_protected:Npn \__siunitx_unit_format_parsed: { + \str_if_eq:NNTF + \l__siunitx_unit_per_inline_str + \l__siunitx_unit_per_display_str + { \__siunitx_unit_format_parsed:V \l__siunitx_unit_per_inline_str } + { + \group_begin: + \__siunitx_unit_format_parsed:V \l__siunitx_unit_per_inline_str + \exp_args:NNNV \group_end: + \tl_set:Nn \l__siunitx_unit_tmp_tl \l__siunitx_unit_formatted_tl + \group_begin: + \__siunitx_unit_format_parsed:V \l__siunitx_unit_per_display_str + \exp_args:NNNV \group_end: + \tl_set:Nn \l__siunitx_unit_formatted_tl \l__siunitx_unit_formatted_tl + \tl_set:Nx \l__siunitx_unit_formatted_tl + { + \mathchoice + { \exp_not:V \l__siunitx_unit_formatted_tl } + { \exp_not:V \l__siunitx_unit_tmp_tl } + { \exp_not:V \l__siunitx_unit_tmp_tl } + { \exp_not:V \l__siunitx_unit_tmp_tl } + } + } + } +\cs_new_protected:Npn \__siunitx_unit_format_parsed:n #1 + { \int_set_eq:NN \l__siunitx_unit_total_int \l__siunitx_unit_position_int + \use:c { __siunitx_unit_format_init_ #1 : } \tl_clear:N \l__siunitx_unit_denominator_tl \tl_clear:N \l__siunitx_unit_formatted_tl \fp_zero:N \l__siunitx_unit_prefix_fp @@ -5660,6 +6225,7 @@ \l__siunitx_unit_position_int < \l__siunitx_unit_total_int { \bool_set_false:N \l__siunitx_unit_bracket_bool + \bool_set_false:N \l__siunitx_unit_current_script_bool \tl_clear:N \l__siunitx_unit_current_tl \bool_set_false:N \l__siunitx_unit_font_bool \bool_set_true:N \l__siunitx_unit_numerator_bool @@ -5670,6 +6236,7 @@ } \__siunitx_unit_format_finalise: } +\cs_generate_variant:Nn \__siunitx_unit_format_parsed:n { V } \cs_new_protected:Npn \__siunitx_unit_format_parsed_aux:n #1 { \tl_set:Nx \l__siunitx_unit_tmp_tl @@ -5678,6 +6245,41 @@ \l__siunitx_unit_tmp_tl \l__siunitx_unit_part_tl { \use:c { __siunitx_unit_format_ #1 : } } } +\cs_new_protected:Npn \__siunitx_unit_format_init_fraction: + { + \bool_set_false:N \l__siunitx_unit_per_symbol_bool + \bool_set_true:N \l__siunitx_unit_powers_positive_bool + \bool_set_true:N \l__siunitx_unit_two_part_bool + } +\cs_new_protected:Npn \__siunitx_unit_format_init_power: + { + \bool_set_false:N \l__siunitx_unit_per_symbol_bool + \bool_set_false:N \l__siunitx_unit_powers_positive_bool + \bool_set_false:N \l__siunitx_unit_two_part_bool + } +\cs_new_protected:cpn { __siunitx_unit_format_init_power-positive-first: } + { + \bool_set_false:N \l__siunitx_unit_per_symbol_bool + \bool_set_false:N \l__siunitx_unit_powers_positive_bool + \bool_set_true:N \l__siunitx_unit_two_part_bool + } +\cs_new_protected:cpn { __siunitx_unit_format_init_repeated-symbol: } + { + \bool_set_true:N \l__siunitx_unit_per_symbol_bool + \bool_set_true:N \l__siunitx_unit_powers_positive_bool + \bool_set_false:N \l__siunitx_unit_two_part_bool + } +\cs_new_protected:Npn \__siunitx_unit_format_init_symbol: + { + \bool_set_true:N \l__siunitx_unit_per_symbol_bool + \bool_set_true:N \l__siunitx_unit_powers_positive_bool + \bool_set_true:N \l__siunitx_unit_two_part_bool + } +\cs_new_protected:cpn { __siunitx_unit_format_init_single-symbol: } + { + \__siunitx_unit_format_init_power: + \__siunitx_unit_format_symbol_or_power: + } \cs_new_protected:Npn \__siunitx_unit_format_combine_exp: { \prop_get:NnNF \l__siunitx_unit_parsed_prop { power-1 } \l__siunitx_unit_tmp_tl @@ -5690,7 +6292,7 @@ \l__siunitx_unit_tmp_tl \l__siunitx_unit_tmp_tl { \prop_get:NnN \l__siunitx_unit_parsed_prop { prefix-1 } \l__siunitx_unit_tmp_tl - \msg_error:nnx { siunitx } { unit / non-numeric-exponent } + \msg_error:nnx { siunitx } { non-numeric-exponent } { \l__siunitx_unit_tmp_tl } \tl_set:Nn \l__siunitx_unit_tmp_tl { 0 } } @@ -5705,7 +6307,7 @@ \l__siunitx_unit_tmp_tl \l__siunitx_unit_tmp_tl { \prop_put:NnV \l__siunitx_unit_parsed_prop { prefix-1 } \l__siunitx_unit_tmp_tl } { - \msg_error:nnx { siunitx } { unit / non-convertible-exponent } + \msg_error:nnx { siunitx } { non-convertible-exponent } { \l__siunitx_unit_tmp_tl } } } @@ -5750,6 +6352,28 @@ } } } +\cs_new_protected:Npn \__siunitx_unit_format_symbol_or_power: + { + \int_compare:nNnT \l__siunitx_unit_total_int > 1 + { + \bool_set_false:N \l__siunitx_unit_tmp_bool + \int_step_inline:nn \l__siunitx_unit_total_int + { + \prop_get:NnNT \l__siunitx_unit_parsed_prop { power- ##1 } + \l__siunitx_unit_tmp_tl + { + \int_compare:nNnT \l__siunitx_unit_tmp_tl < 0 + { + \bool_if:NTF \l__siunitx_unit_tmp_bool + { \bool_set_false:N \l__siunitx_unit_tmp_bool } + { \bool_set_true:N \l__siunitx_unit_tmp_bool } + } + } + } + \bool_if:NT \l__siunitx_unit_tmp_bool + { \__siunitx_unit_format_init_symbol: } + } + } \cs_new:Npn \__siunitx_unit_format_bracket:N #1 { \bool_if:NTF \l__siunitx_unit_bracket_bool @@ -5763,12 +6387,12 @@ \cs_new_protected:Npn \__siunitx_unit_format_power: { \__siunitx_unit_format_font: - \exp_after:wN \__siunitx_unit_format_power_aux:wTF + \exp_after:wN \__siunitx_unit_format_power_aux:w \l__siunitx_unit_part_tl - \q_stop { \__siunitx_unit_format_power_negative: } { \__siunitx_unit_format_power_positive: } } -\cs_new:Npn \__siunitx_unit_format_power_aux:wTF #1 - #2 \q_stop +\cs_new:Npn \__siunitx_unit_format_power_aux:w #1 - #2 \q_stop { \tl_if_empty:nTF {#1} } \cs_new_protected:Npn \__siunitx_unit_format_power_positive: { \__siunitx_unit_format_power_superscript: } @@ -5791,8 +6415,20 @@ { \exp_not:n {#1} } \cs_new_protected:Npn \__siunitx_unit_format_power_superscript: { - \exp_after:wN \__siunitx_unit_format_power_superscipt:w - \l__siunitx_unit_part_tl . . \q_stop + \bool_lazy_and:nnTF + { \l__siunitx_unit_half_sqrt_bool } + { \str_if_eq_p:Vn \l__siunitx_unit_part_tl { 0.5 } } + { + \tl_set:Nx \l__siunitx_unit_current_tl + { + \exp_not:N \sqrt + { \exp_not:V \l__siunitx_unit_current_tl } + } + } + { + \exp_after:wN \__siunitx_unit_format_power_superscipt:w + \l__siunitx_unit_part_tl . . \q_stop + } } \cs_new_protected:Npn \__siunitx_unit_format_power_superscipt:w #1 . #2 . #3 \q_stop { @@ -5822,6 +6458,7 @@ ^ { \siunitx_number_output:N \l__siunitx_unit_tmp_tl } } } + \bool_set_true:N \l__siunitx_unit_current_script_bool \bool_set_false:N \l__siunitx_unit_bracket_bool } \cs_new_protected:Npn \__siunitx_unit_format_prefix: @@ -5866,6 +6503,7 @@ { \tl_set_eq:NN \l__siunitx_unit_current_tl \l__siunitx_unit_part_tl } \cs_new_protected:Npn \__siunitx_unit_format_qualifier: { + \bool_set_false:N \l__siunitx_unit_current_script_bool \use:c { __siunitx_unit_format_qualifier_ @@ -5940,6 +6578,8 @@ } \cs_new_protected:Npn \__siunitx_unit_format_output_aux: { + \bool_set_eq:NN \l__siunitx_unit_script_bool + \l__siunitx_unit_current_script_bool \__siunitx_unit_format_output_aux:nV { formatted } \l__siunitx_unit_product_tl } @@ -6005,29 +6645,9 @@ { \tl_if_empty:NT \l__siunitx_unit_formatted_tl { \tl_set:Nn \l__siunitx_unit_formatted_tl { 1 } } - \bool_if:NTF \l__siunitx_unit_autofrac_bool - { \__siunitx_unit_format_finalise_autofrac: } - { - \bool_if:NTF \l__siunitx_unit_per_symbol_bool - { \__siunitx_unit_format_finalise_symbol: } - { \__siunitx_unit_format_finalise_fraction: } - } - } -\cs_new_protected:Npn \__siunitx_unit_format_finalise_autofrac: - { - \group_begin: - \__siunitx_unit_format_finalise_fraction: - \exp_args:NNNV \group_end: - \tl_set:Nn \l__siunitx_unit_tmp_tl \l__siunitx_unit_formatted_tl - \__siunitx_unit_format_finalise_symbol: - \tl_set:Nx \l__siunitx_unit_formatted_tl - { - \mathchoice - { \exp_not:V \l__siunitx_unit_tmp_tl } - { \exp_not:V \l__siunitx_unit_formatted_tl } - { \exp_not:V \l__siunitx_unit_formatted_tl } - { \exp_not:V \l__siunitx_unit_formatted_tl } - } + \bool_if:NTF \l__siunitx_unit_per_symbol_bool + { \__siunitx_unit_format_finalise_symbol: } + { \__siunitx_unit_format_finalise_fraction: } } \cs_new_protected:Npn \__siunitx_unit_format_finalise_fraction: { @@ -6043,6 +6663,8 @@ \tl_set:Nx \l__siunitx_unit_formatted_tl { \exp_not:V \l__siunitx_unit_formatted_tl + \bool_if:NT \l__siunitx_unit_script_bool + { \exp_not:V \l__siunitx_unit_per_script_tl } \exp_not:V \l__siunitx_unit_per_symbol_tl \__siunitx_unit_format_bracket:N \l__siunitx_unit_denominator_tl } @@ -6157,62 +6779,81 @@ \siunitx_declare_unit:Nx \percent { \cs_to_str:N \% } \siunitx_declare_power:NNn \square \squared { 2 } \siunitx_declare_power:NNn \cubic \cubed { 3 } -\msg_new:nnnn { siunitx } { unit / dangling-part } +\msg_new:nnnn { siunitx } { dangling-part } { Found~#1~part~with~no~unit. } { Each~#1~part~must~be~associated~with~a~unit:~a~#1~part~was~found~ but~no~following~unit~was~given. } -\msg_new:nnnn { siunitx } { unit / duplicate-part } +\msg_new:nnnn { siunitx } { duplicate-part } { Duplicate~#1~part:~#2. } { Each~unit~may~have~only~one~#1:\\ the~additional~#1~part~'#2'~will~be~ignored. } -\msg_new:nnnn { siunitx } { unit / duplicate-sticky-per } +\msg_new:nnnn { siunitx } { duplicate-sticky-per } { Duplicate~\token_to_str:N \per. } { When~the~'sticky-per'~option~is~active,~only~one~ \token_to_str:N \per \ may~appear~in~a~unit. } -\msg_new:nnnn { siunitx } { unit / literal } +\msg_new:nnnn { siunitx } { literal-unit } { Literal~units~disabled. } { You~gave~the~literal~input~'#1'~ but~literal~unit~output~is~disabled. } -\msg_new:nnnn { siunitx } { unit / non-convertible-exponent } +\msg_new:nnnn { siunitx } { non-convertible-exponent } { Exponent~'#1'~cannot~be~converted~into~a~symbolic~prefix. } { The~exponent~'#1'~does~not~match~with~any~of~the~symbolic~prefixes~ set~up. } -\msg_new:nnnn { siunitx } { unit / non-numeric-exponent } +\msg_new:nnnn { siunitx } { non-numeric-exponent } { Prefix~'#1'~does~not~have~a~numerical~value. } { The~prefix~'#1'~needs~to~be~combined~with~a~number,~but~it~has~no numerical~value. } -\msg_new:nnnn { siunitx } { unit / part-before-unit } +\msg_new:nnnn { siunitx } { part-before-unit } { Found~#1~part~before~first~unit:~#2. } { The~#1~part~'#2'~must~follow~after~a~unit:~ it~cannot~appear~before~any~units~and~will~therefore~be~ignored. } +\keys_define:nn { siunitx } + { + display-per-mode / symbol-or-fraction .code:n = + { + \msg_info:nnnn { siunitx } { option-deprecated } + { per-mode~=~symbol-or-fraction } + { display-per-mode~=~fraction,~inline-per-mode~=~symbol } + \str_set:Nn \l__siunitx_unit_per_display_str { fraction } + } , + inline-per-mode / symbol-or-fraction .code:n = + { + \msg_info:nnnn { siunitx } { option-deprecated } + { per-mode~=~symbol-or-fraction } + { display-per-mode~=~fraction,~inline-per-mode~=~symbol } + \str_set:Nn \l__siunitx_unit_per_inline_str { symbol } + } + } \keys_set:nn { siunitx } { - bracket-unit-denominator = true , - forbid-literal-units = false , - fraction-command = \frac , - inter-unit-product = \, , - extract-mass-in-kilograms = true , - parse-units = true , - per-mode = power , - per-symbol = / , - qualifier-mode = subscript , - qualifier-phrase = , - sticky-per = false , - unit-font-command = \mathrm + bracket-unit-denominator = true , + forbid-literal-units = false , + fraction-command = \frac , + inter-unit-product = \, , + extract-mass-in-kilograms = true , + parse-units = true , + per-mode = power , + per-symbol = / , + per-symbol-script-correction = \! , + power-half-as-sqrt = false , + qualifier-mode = subscript , + qualifier-phrase = , + sticky-per = false , + unit-font-command = \mathrm } \AtBeginDocument { @@ -6221,7 +6862,7 @@ { \exp_not:n { \sfdefault } } { \keys_set:nn { siunitx } { unit-font-command = \mathsf } } } -\tl_new:N \l__siunitx_quantity_tmp_fp +\fp_new:N \l__siunitx_quantity_tmp_fp \tl_new:N \l__siunitx_quantity_tmp_tl \tl_new:N \l__siunitx_quantity_bracket_close_tl \tl_new:N \l__siunitx_quantity_bracket_open_tl @@ -6632,6 +7273,7 @@ \siunitx_declare_unit:Nn \g { \gram } \siunitx_declare_unit:Nn \kg { \kilo \gram } \siunitx_declare_unit:Nn \W { \watt } +\siunitx_declare_unit:Nn \nW { \nano \watt } \siunitx_declare_unit:Nn \uW { \micro \watt } \siunitx_declare_unit:Nn \mW { \milli \watt } \siunitx_declare_unit:Nn \kW { \kilo \watt } @@ -6664,9 +7306,16 @@ \siunitx_declare_unit:Nn \pF { \pico \farad } \siunitx_declare_unit:Nn \nF { \nano \farad } \siunitx_declare_unit:Nn \uF { \micro \farad } -\siunitx_declare_unit:Nn \H { \henry } -\siunitx_declare_unit:Nn \mH { \milli \henry } -\siunitx_declare_unit:Nn \uH { \micro \henry } +\siunitx_declare_unit:Nn \H { \henry } +\siunitx_declare_unit:Nn \fH { \femto \henry } +\siunitx_declare_unit:Nn \pH { \pico \henry } +\siunitx_declare_unit:Nn \nH { \nano \henry } +\siunitx_declare_unit:Nn \uH { \micro \henry } +\siunitx_declare_unit:Nn \mH { \milli \henry } +\siunitx_declare_unit:Nn \C { \coulomb } +\siunitx_declare_unit:Nn \nC { \nano \coulomb } +\siunitx_declare_unit:Nn \uC { \micro \coulomb } +\siunitx_declare_unit:Nn \mC { \milli \coulomb } \siunitx_declare_unit:Nn \N { \newton } \siunitx_declare_unit:Nn \mN { \milli \newton } \siunitx_declare_unit:Nn \kN { \kilo \newton } @@ -6793,22 +7442,21 @@ unit-optional-argument = false , use-xspace = false } -\msg_new:nnn { siunitx } { option-deprecated } - { - Option~"#1"~has~been~deprecated~in~this~release.\\ \\ - Use~"#2"~as~a~replacement. - } \msg_new:nnn { siunitx } { option-removed } { Option~"#1"~has~been~removed~in~this~release. } \cs_new_protected:Npn \__siunitx_option_deprecated:nn #1#2 { - \msg_info:nnnn { siunitx } { option-deprecated } {#1} {#2} + \__siunitx_deprecated_info:nn {#1} {#2} \keys_set:nn { siunitx } {#2} } \cs_new_protected:Npn \__siunitx_option_deprecated:nnn #1#2#3 { - \msg_info:nnnn { siunitx } { option-deprecated } {#1} {#2} - \keys_set:nn { siunitx } { #2 = #3 } + \str_if_eq:nnTF {#3} { true } + { \__siunitx_option_deprecated:nn {#1} {#2} } + { + \__siunitx_deprecated_info:nn {#1} { #2 ~=~ #3 } + \keys_set:nn { siunitx } { #2 = #3 } + } } \cs_generate_variant:Nn \__siunitx_option_deprecated:nnn { nnV } \cs_new_protected:Npn \__siunitx_option_removed:n #1 @@ -7317,18 +7965,6 @@ } , literal-superscript-as-power .code:n = { \__siunitx_option_removed:V \l_keys_key_tl } , - per-mode / reciprocal .code:n = - { - \__siunitx_option_deprecated:nn - { per-mode~=~reciprocal } - { per-mode~=~power } - } , - per-mode / reciprocal-positive-first .code:n = - { - \__siunitx_option_deprecated:nn - { per-mode~=~reciprocal-positive-first } - { per-mode~=~power-positive-first } - } , power-font .code:n = { \__siunitx_option_removed:V \l_keys_key_tl } , qualifier-mode / brackets .code:n = @@ -7355,6 +7991,33 @@ } \keys_define:nn { siunitx } { + display-per-mode / reciprocal .code:n = + { + \__siunitx_option_deprecated:nn + { per-mode~=~reciprocal } + { per-mode~=~power } + } , + inline-per-mode / reciprocal .code:n = + { + \__siunitx_option_deprecated:nn + { per-mode~=~reciprocal } + { per-mode~=~power } + } , + display-per-mode / reciprocal-positive-first .code:n = + { + \__siunitx_option_deprecated:nn + { per-mode~=~reciprocal-positive-first } + { per-mode~=~power-positive-first } + } , + inline-per-mode / reciprocal-positive-first .code:n = + { + \__siunitx_option_deprecated:nn + { per-mode~=~reciprocal-positive-first } + { per-mode~=~power-positive-first } + } + } +\keys_define:nn { siunitx } + { allow-number-unit-breaks .code:n = { \__siunitx_option_deprecated:nnV @@ -7434,6 +8097,18 @@ { table-column-type = S } +\msg_new:nnn { siunitx } { option-deprecated } + { + Option~"#1"~has~been~deprecated~in~this~release.\\ \\ + Use~"#2"~as~a~replacement. + } +\seq_new:N \g__siunitx_deprecated_seq +\cs_new_protected:Npn \__siunitx_deprecated_info:nn #1#2 + { + \seq_if_in:NnF \g__siunitx_deprecated_seq {#1} + { \msg_info:nnnn { siunitx } { option-deprecated } {#1} {#2} } + \seq_gput_right:Nn \g__siunitx_deprecated_seq {#1} + } \IfFormatAtLeastTF { 2022-06-01 } { \ProcessKeyOptions [ siunitx ] } { @@ -7461,16 +8136,34 @@ { \siunitx_declare_unit:Nn #2 {#3} } { \siunitx_declare_unit:Nnn #2 {#3} {#1} } } -\@ifpackageloaded { physics } +\AtBeginDocument { - \msg_new:nnn { siunitx } { physics-pkg } + \@ifpackageloaded { physics } { - Detected~the~"physics"~package: \\ - Omitting~definition~of~\token_to_str:N \qty. + \msg_new:nnn { siunitx } { physics-pkg } + { + Detected~the~"physics"~package: \\ + omitting~definition~of~\token_to_str:N \qty. + \\ \\ + If~you~want~to~use~\qty with~the~siunitx~definition,~add~ + \\ \\ + \iow_indent:n + { + \token_to_str:N \AtBeginDocument + { + \token_to_str:N \RenewCommandCopy + \token_to_str:N \qty \token_to_str:N \SI + } + } + \\ \\ + to~your~preamble. + } + \msg_warning:nn { siunitx } { physics-pkg } } - \msg_warning:nn { siunitx } { physics-pkg } - \use_none:nnnn + { } } +\@ifpackageloaded { physics } + { \use_none:nnnn } { } \NewDocumentCommand \qty { O { } m > { \TrimSpaces } m } { @@ -7498,17 +8191,6 @@ \siunitx_print_number:V \l__siunitx_tmp_tl \group_end: } -\@ifpackageloaded { units } - { - \msg_new:nnn { siunitx } { units-pkg } - { - Detected~the~"units"~package: \\ - Omitting~definition~of~\token_to_str:N \unit. - } - \msg_warning:nn { siunitx } { units-pkg } - \use_none:nnnn - } - { } \NewDocumentCommand \unit { O { } > { \TrimSpaces } m } { \mode_leave_vertical: @@ -7573,21 +8255,29 @@ \siunitx_number_range:nn {#2} {#3} \group_end: } -\NewDocumentCommand \complexnum { O { } m } +\use:e + { + \NewDocumentCommand \exp_not:N \complexnum + { O { } > { \SplitArgument { 1 } { \c_colon_str } } m } + } { \mode_leave_vertical: \group_begin: \keys_set:nn { siunitx } {#1} - \siunitx_complex_number:n {#2} \l__siunitx_tmp_tl + \__siunitx_complex_number_aux:nn #2 \group_end: } -\NewDocumentCommand \complexqty { O { } m m } +\use:e + { + \NewDocumentCommand \exp_not:N \complexqty + { O { } > { \SplitArgument { 1 } { \c_colon_str } } m m } + } { \mode_leave_vertical: \group_begin: \siunitx_unit_options_apply:n {#3} \keys_set:nn { siunitx } {#1} - \siunitx_complex_quantity:nn {#2} {#3} + \__siunitx_complex_quantity_aux:nnn #2 {#3} \group_end: } \NewDocumentCommand \tablenum { O { } m } @@ -7612,6 +8302,18 @@ { \siunitx_angle:nnn {#1} {#2} {#3} } } } +\cs_new_protected:Npn \__siunitx_complex_number_aux:nn #1#2 + { + \tl_if_novalue:nTF {#2} + { \siunitx_complex_number:n {#1} } + { \siunitx_complex_number:nn {#1} {#2} } + } +\cs_new_protected:Npn \__siunitx_complex_quantity_aux:nnn #1#2#3 + { + \tl_if_novalue:nTF {#2} + { \siunitx_complex_quantity:nn {#1} {#3} } + { \siunitx_complex_quantity:nnn {#1} {#2} {#3} } + } \RequirePackage { array } \cs_new_protected:Npn \__siunitx_declare_column:Nnn #1#2#3 { @@ -7815,19 +8517,21 @@ \siunitx_declare_power:NNn \__siunitx_tmp:w #1 {#2} \seq_remove_all:Nn \l_siunitx_unit_symbolic_seq { \__siunitx_tmp:w } } -\NewDocumentCommand \si { O { } m } +\NewDocumentCommand \si { O { } > { \TrimSpaces } m } { \mode_leave_vertical: \group_begin: + \siunitx_unit_options_apply:n {#2} \keys_set:nn { siunitx } {#1} \siunitx_unit_format:nN {#2} \l__siunitx_tmp_tl \siunitx_print_unit:V \l__siunitx_tmp_tl \group_end: } -\NewDocumentCommand \SI { O { } m o m } +\NewDocumentCommand \SI { O { } m o > { \TrimSpaces } m } { \mode_leave_vertical: \group_begin: + \siunitx_unit_options_apply:n {#4} \keys_set:nn { siunitx } {#1} \IfNoValueF {#3} { |