texlive[67780] Master/texmf-dist: siunitx (31jul23)

commits+karl at tug.org commits+karl at tug.org
Mon Jul 31 22:18:52 CEST 2023


Revision: 67780
          http://tug.org/svn/texlive?view=revision&revision=67780
Author:   karl
Date:     2023-07-31 22:18:52 +0200 (Mon, 31 Jul 2023)
Log Message:
-----------
siunitx (31jul23)

Modified Paths:
--------------
    trunk/Master/texmf-dist/doc/latex/siunitx/CHANGELOG.md
    trunk/Master/texmf-dist/doc/latex/siunitx/siunitx-code.pdf
    trunk/Master/texmf-dist/doc/latex/siunitx/siunitx.pdf
    trunk/Master/texmf-dist/source/latex/siunitx/siunitx-abbreviation.dtx
    trunk/Master/texmf-dist/source/latex/siunitx/siunitx-angle.dtx
    trunk/Master/texmf-dist/source/latex/siunitx/siunitx-compound.dtx
    trunk/Master/texmf-dist/source/latex/siunitx/siunitx-locale.dtx
    trunk/Master/texmf-dist/source/latex/siunitx/siunitx-number.dtx
    trunk/Master/texmf-dist/source/latex/siunitx/siunitx-table.dtx
    trunk/Master/texmf-dist/source/latex/siunitx/siunitx.dtx
    trunk/Master/texmf-dist/source/latex/siunitx/siunitx.ins
    trunk/Master/texmf-dist/source/latex/siunitx/siunitx.tex
    trunk/Master/texmf-dist/tex/latex/siunitx/siunitx.sty

Modified: trunk/Master/texmf-dist/doc/latex/siunitx/CHANGELOG.md
===================================================================
--- trunk/Master/texmf-dist/doc/latex/siunitx/CHANGELOG.md	2023-07-31 20:11:33 UTC (rev 67779)
+++ trunk/Master/texmf-dist/doc/latex/siunitx/CHANGELOG.md	2023-07-31 20:18:52 UTC (rev 67780)
@@ -7,6 +7,49 @@
 
 ## [Unreleased]
 
+## [v3.3.0] - 2023-07-31
+
+### Added
+- Support for Italian (see issue
+  [\#650](https://github.com/josephwright/siunitx/issues/650))
+- Abbreviations `\T`, `\mT`, `\uT` (see issue
+  [\#670](https://github.com/josephwright/siunitx/issues/670))
+- Option `range-open-phrase`
+- Option `round-direction` to allow 'truncation' of rounded
+  values (see issue
+  [\#664](https://github.com/josephwright/siunitx/issues/664))
+- Option `uncertainty-round-direction` (see issue
+  [\#628](https://github.com/josephwright/siunitx/issues/628))
+- Support for asymmetrical uncertainties, including new option
+  `input-uncertainty-divider` (see issue
+  [\#675](https://github.com/josephwright/siunitx/issues/675))
+- Options for bracket control:
+  - `compound-close-bracket`
+  - `compound-open-bracket`
+  - `list-close-bracket`
+  - `list-open-bracket`
+  - `product-close-bracket` 
+  - `product-open-bracket` 
+  - `range-close-bracket` 
+  - `range-open-bracket` 
+  (see issue
+  [\#262](https://github.com/josephwright/siunitx/issues/262))
+- Option `table-model-setup` (see issue
+  [\#659](https://github.com/josephwright/siunitx/issues/659))
+- Options `list-input-separator` and `product-input-separator` (see issue
+  [\#603](https://github.com/josephwright/siunitx/issues/603))
+- Options `compound-independent-prefix`, `list-independent-prefix`,
+  `product-independent-prefix` and `range-independent-prefix` (see issue
+  [\#554](https://github.com/josephwright/siunitx/issues/554))
+- Hint for overloading `\num` and `\qty` (see issue
+  [\#648](https://github.com/josephwright/siunitx/issues/648))
+
+### Changed
+
+- Support bracing of decimal marker in tables as an alternative
+  to `\mathord` (see issue
+  [\#527](https://github.com/josephwright/siunitx/issues/527))
+
 ## [v3.2.9] - 2023-07-26
 
 ### Fixed
@@ -1928,7 +1971,8 @@
 ### Added
 - First public testing release (as `si`)
 
-[Unreleased]: https://github.com/josephwright/siunitx/compare/v3.2.9...HEAD
+[Unreleased]: https://github.com/josephwright/siunitx/compare/v3.3.0...HEAD
+[v3.3.0]: https://github.com/josephwright/siunitx/compare/v3.2.9...v3.3.0
 [v3.2.9]: https://github.com/josephwright/siunitx/compare/v3.2.8...v3.2.9
 [v3.2.8]: https://github.com/josephwright/siunitx/compare/v3.2.7...v3.2.8
 [v3.2.7]: https://github.com/josephwright/siunitx/compare/v3.2.6...v3.2.7

Modified: trunk/Master/texmf-dist/doc/latex/siunitx/siunitx-code.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/doc/latex/siunitx/siunitx.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/source/latex/siunitx/siunitx-abbreviation.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/siunitx/siunitx-abbreviation.dtx	2023-07-31 20:11:33 UTC (rev 67779)
+++ trunk/Master/texmf-dist/source/latex/siunitx/siunitx-abbreviation.dtx	2023-07-31 20:18:52 UTC (rev 67780)
@@ -127,6 +127,10 @@
 %   Abbreviations for charge.
 % \end{function}
 %
+% \begin{function}{\T, \mT \uT}
+%   Abbreviations for magneticc field.
+% \end{function}
+%
 % \begin{function}{\dB}
 %   Abbreviation for decibel.
 % \end{function}
@@ -306,6 +310,14 @@
 \siunitx_declare_unit:Nn \mC  { \milli \coulomb }
 %    \end{macrocode}
 % \end{macro}
+% \begin{macro}{\T, \uT, \mT}
+%   Magnetic field.
+%    \begin{macrocode}
+\siunitx_declare_unit:Nn \T   { \tesla }
+\siunitx_declare_unit:Nn \uT  { \micro \tesla }
+\siunitx_declare_unit:Nn \mT  { \milli \tesla }
+%    \end{macrocode}
+% \end{macro}
 % \begin{macro}{\N, \mN, \kN, \MN}
 %   Forces.
 %    \begin{macrocode}

Modified: trunk/Master/texmf-dist/source/latex/siunitx/siunitx-angle.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/siunitx/siunitx-angle.dtx	2023-07-31 20:11:33 UTC (rev 67779)
+++ trunk/Master/texmf-dist/source/latex/siunitx/siunitx-angle.dtx	2023-07-31 20:18:52 UTC (rev 67780)
@@ -337,6 +337,30 @@
 %    \end{macrocode}
 % \end{variable}
 %
+% \begin{macro}{\@@_suppress_exp_uncert:, \@@_suppress_comp_sign:}
+%   Pre-compilation of keys to suppress uncertainties and exponents,
+%   and 
+%    \begin{macrocode}
+\keys_precompile:nnN
+  { siunitx }
+  {
+    input-close-uncertainty = ,
+    input-exponent-markers  = ,
+    input-open-uncertainty  = ,
+    input-uncertainty-signs =
+  }
+  \l_@@_tmp_tl
+\cs_set_protected:Npx \@@_suppress_exp_uncert:
+  { \exp_not:V \l_@@_tmp_tl }
+\keys_precompile:nnN
+  { siunitx }
+  { input-comparators = , input-signs = }
+  \l_@@_tmp_tl
+\cs_set_protected:Npx \@@_suppress_comp_sign:
+  { \exp_not:V \l_@@_tmp_tl }
+%    \end{macrocode}
+% \end{macro}
+%
 % \begin{macro}{\@@_arc_sign:nnn}
 % \begin{macro}{\@@_arc_sign:nn}
 % \begin{macro}{\@@_extract_sign:nnnnnnnn}
@@ -348,13 +372,7 @@
 \cs_new_protected:Npn \@@_arc_sign:nnn #1#2#3
   {
     \group_begin:
-      \keys_set:nn { siunitx }
-        {
-          input-close-uncertainty = ,
-          input-exponent-markers  = ,
-          input-open-uncertainty  = ,
-          input-uncertainty-signs =
-        }
+      \@@_suppress_exp_uncert:
       \tl_clear:N \l_@@_sign_tl
       \@@_arc_sign:nn {#1} { degrees }
       \@@_arc_sign:nn {#2} { minutes }
@@ -420,8 +438,7 @@
         \tl_set:cn { l_@@_ #8 _tl }
           { {#1} { } {#3} {#4} {#5} {#6} {#7} }
         \tl_set:Nn \l_@@_sign_tl {#2}
-        \keys_set:nn { siunitx }
-          { input-comparators = , input-signs = }
+        \@@_suppress_comp_sign:
       }
   }
 \cs_new:Npn \@@_sign:nnnnnnn #1#2#3#4#5#6#7

Modified: trunk/Master/texmf-dist/source/latex/siunitx/siunitx-compound.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/siunitx/siunitx-compound.dtx	2023-07-31 20:11:33 UTC (rev 67779)
+++ trunk/Master/texmf-dist/source/latex/siunitx/siunitx-compound.dtx	2023-07-31 20:18:52 UTC (rev 67780)
@@ -137,6 +137,35 @@
 %   Phrase (or similar) used between limits of a range.
 % \end{variable}
 %
+% \begin{function}{compound-boundary-mode}
+%   \begin{syntax}
+%     |compound-boundary-mode| = |number|\verb"|"|text|
+%   \end{syntax}
+%   Choice which determines whether the material at the start and
+%   end of a compound quantity are typeset a |number| or as |text|;
+%   the latter is the standard setting.
+% \end{function}
+%
+% \begin{function}{compound-close-boundary, compound-open-boundary}
+%   \begin{syntax}
+%     |compound-close-boundary| = \meta{tokens}\\
+%     |compound-open-boundary|  = \meta{tokens}
+%   \end{syntax}
+%   Literals which are inserted at the opening and closing boundary of a compound
+%   quantity; they are not used when the number of items is one.
+%   The standard settings set these empty.
+% \end{function}
+%
+% \begin{function}{compound-close-bracket, compound-open-bracket}
+%   \begin{syntax}
+%     |compound-close-bracket| = \meta{token} \\
+%     |compound-open-bracket|  = \meta{token}
+%   \end{syntax}
+%   Literals containing the tokens inserted at the start and end of a compound
+%   value when |compounds-units| is set to |bracket|. The standard settings are
+%   |(| and |)|.
+% \end{function}
+%
 % \begin{function}{compound-exponents}
 %   \begin{syntax}
 %     |compound-exponents| = |combine|\verb"|"|combine-bracket|\verb"|"|individual|
@@ -149,6 +178,15 @@
 %   \end{syntax}
 % \end{function}
 %
+% \begin{function}{compound-independent-prefix}
+%   \begin{syntax}
+%     |compound-independent-prefix| = |true|\verb"|"|false|
+%   \end{syntax}
+%   Switch which determines whether unit prefixes are calculated
+%   independently when units are repeated. The standard setting is
+%   |false|.
+% \end{function}
+%
 % \begin{function}{compound-pair-separator}
 %   \begin{syntax}
 %     |compound-pair-separator| = \meta{text}
@@ -165,6 +203,9 @@
 %   \begin{syntax}
 %     |compound-separator-mode| = |number|\verb"|"|text|
 %   \end{syntax}
+%   Choice which determines whether the separators between components
+%   of compound quantity are typeset a |number| or as |text|;
+%   the latter is the standard setting.
 % \end{function}
 %
 % \begin{function}{compound-units}
@@ -173,6 +214,15 @@
 %   \end{syntax}
 % \end{function}
 %
+% \begin{function}{list-close-bracket, list-open-bracket}
+%   \begin{syntax}
+%     |list-close-bracket| = \meta{token} \\
+%     |list-open-bracket|  = \meta{token}
+%   \end{syntax}
+%   Literals containing the tokens inserted at the start and end of a list when
+%   |list-units| is set to |bracket|. The standard settings are |(| and |)|.
+% \end{function}
+%
 % \begin{function}{list-exponents}
 %   \begin{syntax}
 %     |list-exponents| = |combine|\verb"|"|combine-bracket|\verb"|"|individual|
@@ -185,6 +235,15 @@
 %   \end{syntax}
 % \end{function}
 %
+% \begin{function}{list-independent-prefix}
+%   \begin{syntax}
+%     |list-independent-prefix| = |true|\verb"|"|false|
+%   \end{syntax}
+%   Switch which determines whether unit prefixes are calculated
+%   independently when units are repeated. The standard setting is
+%   |false|.
+% \end{function}
+%
 % \begin{function}{list-pair-separator}
 %   \begin{syntax}
 %     |list-pair-separator| = \meta{text}
@@ -203,6 +262,16 @@
 %   \end{syntax}
 % \end{function}
 %
+% \begin{function}{product-close-bracket, product-open-bracket}
+%   \begin{syntax}
+%     |product-close-bracket| = \meta{token} \\
+%     |product-open-bracket|  = \meta{token}
+%   \end{syntax}
+%   Literals containing the tokens inserted at the start and end of a product
+%   when |product-units| is set to |bracket|. The standard settings are |(|
+%   and |)|.
+% \end{function}
+%
 % \begin{function}{product-exponents}
 %   \begin{syntax}
 %     |product-exponents| = |combine|\verb"|"|combine-bracket|\verb"|"|individual|
@@ -209,6 +278,15 @@
 %   \end{syntax}
 % \end{function}
 %
+% \begin{function}{product-independent-prefix}
+%   \begin{syntax}
+%     |product-independent-prefix| = |true|\verb"|"|false|
+%   \end{syntax}
+%   Switch which determines whether unit prefixes are calculated
+%   independently when units are repeated. The standard setting is
+%   |false|.
+% \end{function}
+%
 % \begin{function}{product-mode}
 %   \begin{syntax}
 %     |product-mode| = |phrase|\verb"|"|choice|
@@ -233,10 +311,40 @@
 %   \end{syntax}
 % \end{function}
 %
+% \begin{function}{range-close-bracket, range-open-bracket}
+%   \begin{syntax}
+%     |range-close-bracket| = \meta{token} \\
+%     |range-open-bracket|  = \meta{token}
+%   \end{syntax}
+%   Literals containing the tokens inserted at the start and end of a range when
+%   |range-units| is set to |bracket|. The standard settings are |(| and |)|.
+% \end{function}
+%
+% \begin{function}{range-independent-prefix}
+%   \begin{syntax}
+%     |range-independent-prefix| = |true|\verb"|"|false|
+%   \end{syntax}
+%   Switch which determines whether unit prefixes are calculated
+%   independently when units are repeated. The standard setting is
+%   |false|.
+% \end{function}
+%
+% \begin{function}{range-open-phrase}
+%   \begin{syntax}
+%     |range-open-phrase| = \meta{text}
+%   \end{syntax}
+%   Literal containing the material to be inserted at the start of a range.
+%   The standard setting is empty.
+% \end{function}
+%
 % \begin{function}{range-phrase}
 %   \begin{syntax}
 %     |range-phrase| = \meta{text}
 %   \end{syntax}
+%   Literal containing the material to be inserted between the start and end
+%   of a range. The standard setting contains the word \texttt{to} inside the
+%   \cs{text} command, along with appropriate spacing commands to allow this
+%   material to work in both math and text typesetting modes.
 % \end{function}
 %
 % \begin{function}{range-units}
@@ -258,6 +366,7 @@
 %
 %    \begin{macrocode}
 \cs_generate_variant:Nn \keys_set:nn { nx }
+\cs_generate_variant:Nn \seq_use:Nnnn { NVVV }
 %    \end{macrocode}
 %
 % \subsection{General mechanism}
@@ -318,29 +427,26 @@
 %    \end{macrocode}
 % \end{variable}
 %
-% \begin{variable}{\l_@@_bracket_close_tl, \l_@@_bracket_open_tl}
-%   Purely internal for the present.
-%    \begin{macrocode}
-\tl_new:N \l_@@_bracket_close_tl
-\tl_new:N \l_@@_bracket_open_tl
-\tl_set:Nn \l_@@_bracket_open_tl { ( }
-\tl_set:Nn \l_@@_bracket_close_tl { ) }
-%    \end{macrocode}
-% \end{variable}
-%
 % \begin{variable}
 %   {
+%     \l_@@_boundary_close_tl   ,
+%     \l_@@_bracket_close_tl    ,
+%     \l_@@_independent_bool    ,
 %     \l_@@_separator_final_tl  ,
 %     \l_@@_separator_pair_tl   ,
+%     \l_@@_boundary_open_tl    ,
+%     \l_@@_bracket_open_tl     ,
 %     \l_@@_separator_tl        ,
 %     \l_@@_separator_text_bool ,
 %     \l_@@_exp_bracket_bool    ,
 %     \l_@@_exp_combine_bool    ,
 %     \l_@@_unit_bracket_bool   ,
-%     \l_@@_unit_repeat_bool
+%     \l_@@_unit_power_bool     ,
+%     \l_@@_unit_repeat_bool    ,
 %   }
 %   List options.
 %    \begin{macrocode}
+\bool_new:N \l_@@_boundary_text_bool
 \bool_new:N \l_@@_exp_bracket_bool
 \bool_new:N \l_@@_exp_combine_bool
 \bool_new:N \l_@@_separator_text_bool
@@ -349,6 +455,15 @@
 \bool_new:N \l_@@_unit_repeat_bool
 \keys_define:nn { siunitx }
   {
+    compound-boundary-mode .choice: ,
+    compound-boundary-mode / number .code:n =
+      { \bool_set_false:N \l_@@_delim_text_bool } ,
+    compound-boundary-mode / text .code:n =
+      { \bool_set_true:N \l_@@_delim_text_bool } ,
+    compound-close-boundary .tl_set:N =
+      \l_@@_boundary_close_tl ,
+    compound-close-bracket .tl_set:N =
+      \l_@@_bracket_close_tl ,
     compound-exponents .choice: ,
     compound-exponents / combine .code:n =
       {
@@ -367,8 +482,14 @@
       } ,
     compound-final-separator .tl_set:N =
       \l_@@_separator_final_tl ,
+    compound-independent-prefix .bool_set:N =
+      \l_@@_independent_bool , 
     compound-pair-separator .tl_set:N =
       \l_@@_separator_pair_tl ,
+    compound-open-boundary .tl_set:N =
+      \l_@@_boundary_open_tl ,
+    compound-open-bracket .tl_set:N =
+      \l_@@_bracket_open_tl ,
     compound-separator .tl_set:N =
       \l_@@_separator_tl ,
     compound-separator-mode .choice: ,
@@ -406,7 +527,7 @@
         \bool_set_false:N \l_@@_unit_bracket_bool
         \bool_set_false:N \l_@@_unit_power_bool
         \bool_set_false:N \l_@@_unit_repeat_bool
-      }
+      }  
   }
 %    \end{macrocode}
 % \end{variable}
@@ -664,7 +785,12 @@
 % \end{macro}
 % \end{macro}
 %
-% \begin{macro}{\siunitx_compound_quantity:nn}
+% \begin{macro}
+%   {
+%     \siunitx_compound_quantity:nn ,
+%     \@@_quantity_auxi:nn          ,
+%     \@@_quantity_auxii:nn
+%   }
 %   For quantities, life is more complex as there are interactions between the
 %   options for exponents and units. The \cs{c_empty_tl} suppresses any
 %   leading \texttt{1} if the unit starts \cs{per}; the \pkg{siunitx-print}
@@ -673,38 +799,77 @@
 \cs_new_protected:Npn \siunitx_compound_quantity:nn #1#2
   {
     \group_begin:
-      \bool_if:NT \l_@@_unit_bracket_bool
-        { \bool_set_true:N \l_@@_exp_bracket_bool }
-      \bool_if:NT \l_@@_unit_repeat_bool
-        { \bool_set_false:N \l_@@_exp_combine_bool }
-      \bool_lazy_or:nnT
-        { \l_@@_unit_bracket_bool }
-        { ! \l_@@_unit_repeat_bool }
-        { \bool_set_false:N \l_siunitx_number_bracket_ambiguous_bool }
-      \bool_set_true:N \l_@@_unit_bool
-      \@@_format:nn {#1} {#2}
-      \bool_if:NF \l_siunitx_number_parse_bool
-        { \siunitx_unit_format:nN {#2} \l_@@_unit_tl }
-      \str_if_eq:VnT \l_siunitx_quantity_prefix_mode_tl { combine-exponent }
-        { \tl_clear:N \l_@@_exp_tl }
-      \bool_if:NTF \l_@@_unit_repeat_bool
-        { \@@_print:N \@@_print_quantity:x }
+      \bool_lazy_all:nTF
         {
-          \bool_lazy_and:nnTF
-            { \l_@@_unit_bracket_bool }
-            { \tl_if_empty_p:N \l_@@_exp_tl }
-            {
-              \siunitx_print_number:V \l_@@_bracket_open_tl
-              \@@_print:N \siunitx_print_number:x
-              \siunitx_print_number:V \l_@@_bracket_close_tl
-            }
-            { \@@_print:N \siunitx_print_number:x }
-          \@@_print_quantity:n { \c_empty_tl }
+          { \l_@@_independent_bool }
+          {
+            \str_if_eq_p:Vn
+              \l_siunitx_quantity_prefix_mode_tl
+              { combine-exponent }
+          }
+          { \int_compare_p:nNn { \tl_count:n {#1} } > 1 }
         }
+        { \@@_quantity_auxi:nn }
+        { \@@_quantity_auxii:nn }
+          {#1} {#2}
     \group_end:
   }
 %    \end{macrocode}
+%   The rather special case where all units are printed independently:
+%   we just convert to a simple sequence then print.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_quantity_auxi:nn #1#2
+  {
+    \@@_print_boundary:V \l_@@_boundary_close_tl
+    \seq_clear:N \l_@@_tmp_seq
+    \tl_map_inline:nn {#1}
+      {
+        \seq_put_right:Nn \l_@@_tmp_seq
+          { \siunitx_quantity:nn {##1} {#2} }
+      }
+    \seq_use:NVVV \l_@@_tmp_seq
+      \l_@@_separator_pair_tl
+      \l_@@_separator_tl
+      \l_@@_separator_final_tl
+    \@@_print_boundary:V \l_@@_boundary_close_tl
+  }
+%    \end{macrocode}
+%   The business end for all other cases.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_quantity_auxii:nn #1#2
+  {
+    \bool_if:NT \l_@@_unit_bracket_bool
+      { \bool_set_true:N \l_@@_exp_bracket_bool }
+    \bool_if:NT \l_@@_unit_repeat_bool
+      { \bool_set_false:N \l_@@_exp_combine_bool }
+    \bool_lazy_or:nnT
+      { \l_@@_unit_bracket_bool }
+      { ! \l_@@_unit_repeat_bool }
+      { \bool_set_false:N \l_siunitx_number_bracket_ambiguous_bool }
+    \bool_set_true:N \l_@@_unit_bool
+    \@@_format:nn {#1} {#2}
+    \bool_if:NF \l_siunitx_number_parse_bool
+      { \siunitx_unit_format:nN {#2} \l_@@_unit_tl }
+    \str_if_eq:VnT \l_siunitx_quantity_prefix_mode_tl { combine-exponent }
+      { \tl_clear:N \l_@@_exp_tl }
+    \bool_if:NTF \l_@@_unit_repeat_bool
+      { \@@_print:N \@@_print_quantity:x }
+      {
+        \bool_lazy_and:nnTF
+          { \l_@@_unit_bracket_bool }
+          { \tl_if_empty_p:N \l_@@_exp_tl }
+          {
+            \siunitx_print_number:V \l_@@_bracket_open_tl
+            \@@_print:N \siunitx_print_number:x
+            \siunitx_print_number:V \l_@@_bracket_close_tl
+          }
+          { \@@_print:N \siunitx_print_number:x }
+        \@@_print_quantity:n { \c_empty_tl }
+      }
+  }
+%    \end{macrocode}
 % \end{macro}
+% \end{macro}
 %
 % \begin{macro}{\@@_print:N}
 % \begin{macro}{\@@_print:nnN, \@@_print:xxN}
@@ -712,7 +877,11 @@
 % \begin{macro}{\@@_print_aux:n}
 % \begin{macro}{\@@_print_aux:nn}
 % \begin{macro}{\@@_print_quantity:n, \@@_print_quantity:x}
-% \begin{macro}{\@@_print_separator:n, \@@_print_separator:V}
+% \begin{macro}
+%   {
+%     \@@_print_boundary:n, \@@_print_boundary:V,
+%     \@@_print_separator:n, \@@_print_separator:V
+%   }
 %   We now need to know how many entries there are: the reason we don't use
 %   \cs{seq_use:Nnnn} is that we want to be able to insert
 %   \cs{siunitx_print_\dots:n} in a controlled way.
@@ -757,6 +926,7 @@
           }
         { 2 }
           {
+            \@@_print_boundary:V \l_@@_boundary_open_tl
             #4
               {
                 \exp_not:n {#2}
@@ -768,6 +938,7 @@
                 \seq_item:Nn \l_@@_tmp_seq { 2 }
                 \exp_not:n {#3}
               }
+            \@@_print_boundary:V \l_@@_boundary_open_tl
           }
       }
       {
@@ -775,9 +946,11 @@
         \tl_set:Nn \l_@@_start_tl {#2}
         \tl_set:Nn \l_@@_end_tl {#3}
         \cs_set_eq:NN \@@_print_aux:n #4
+        \@@_print_boundary:V \l_@@_boundary_open_tl
         \seq_map_indexed_function:NN
           \l_@@_tmp_seq
           \@@_print_aux:nn
+        \@@_print_boundary:V \l_@@_boundary_close_tl
       }
   }
 \cs_new_protected:Npn \@@_print_aux:n #1 { }
@@ -816,6 +989,16 @@
 \cs_new_protected:Npn \@@_print_quantity:n #1
   { \siunitx_quantity_print:nV {#1} \l_@@_unit_tl }
 \cs_generate_variant:Nn  \@@_print_quantity:n { x }
+\cs_new_protected:Npn \@@_print_boundary:n #1
+  {
+    \tl_if_blank:nF {#1}
+      {
+        \bool_if:NTF \l_@@_boundary_text_bool
+          { #1 }
+          { \siunitx_print_number:n {#1} }
+      }
+  }
+\cs_generate_variant:Nn \@@_print_boundary:n { V }
 \cs_new_protected:Npn \@@_print_separator:n #1
   {
     \bool_if:NTF \l_@@_separator_text_bool
@@ -872,8 +1055,11 @@
 %
 % \begin{variable}
 %   {
+%     \l_@@_bracket_close_tl             ,
+%     \l_@@_independent_bool             ,
 %     \l_siunitx_list_separator_tl       ,
 %     \l_siunitx_list_separator_final_tl ,
+%     \l_@@_bracket_open_tl              ,
 %     \l_siunitx_list_separator_pair_tl  ,
 %     \l_@@_exp_tl                       ,
 %     \l_@@_units_tl
@@ -884,14 +1070,20 @@
 \tl_new:N \l_@@_units_tl
 \keys_define:nn { siunitx }
   {
+    list-close-bracket .tl_set:N =
+      \l_@@_bracket_close_tl ,
     list-exponents .choices:nn =
       { combine , combine-bracket , individual }
       { \tl_set_eq:NN \l_@@_exp_tl \l_keys_choice_tl } ,
     list-final-separator .tl_set:N = \l_siunitx_list_separator_final_tl ,
+    list-independent-prefix .bool_set:N =
+      \l_@@_independent_bool ,
+    list-open-bracket .tl_set:N =
+      \l_@@_bracket_open_tl ,
     list-pair-separator .tl_set:N = \l_siunitx_list_separator_pair_tl ,
     list-separator .tl_set:N = \l_siunitx_list_separator_tl ,
     list-units .choices:nn =
-      { bracket , repeat , single }
+      { bracket , independent , repeat , single }
       { \tl_set_eq:NN \l_@@_units_tl \l_keys_choice_tl }
   }
 %    \end{macrocode}
@@ -920,15 +1112,23 @@
   {
     \keys_set:nx { siunitx }
       {
-        compound-exponents       = \l_@@_exp_tl ,
-        compound-final-separator =
+        compound-close-bracket       =
+          { \exp_not:V \l_@@_bracket_close_tl } ,
+        compound-close-boundary       = ,
+        compound-exponents            = \l_@@_exp_tl ,
+        compound-final-separator      =
           { \exp_not:V \l_siunitx_list_separator_final_tl } ,
-        compound-pair-separator  =
+        compound-independent-prefix =
+          \bool_if:NTF \l_@@_independent_bool { true } { false } ,
+        compound-open-boundary        = ,
+        compound-open-bracket         =
+          { \exp_not:V \l_@@_bracket_open_tl } ,
+        compound-pair-separator       =
           { \exp_not:V \l_siunitx_list_separator_pair_tl } ,
-        compound-separator       =
+        compound-separator            =
           { \exp_not:V \l_siunitx_list_separator_tl } ,
-        compound-separator-mode  = text ,
-        compound-units           = \l_@@_units_tl
+        compound-separator-mode       = text ,
+        compound-units                = \l_@@_units_tl
       }
   }
 %    \end{macrocode}
@@ -946,10 +1146,13 @@
 %
 % \begin{variable}
 %   {
-%     \l_@@_exp_tl      ,
-%     \l_@@_phrase_bool ,
-%     \l_@@_phrase_tl   ,
-%     \l_@@_symbol_tl   ,
+%     \l_@@_bracket_close_tl ,
+%     \l_@@_exp_tl           ,
+%     \l_@@_independent_bool ,
+%     \l_@@_bracket_open_tl  ,
+%     \l_@@_phrase_bool      ,
+%     \l_@@_phrase_tl        ,
+%     \l_@@_symbol_tl        ,
 %     \l_@@_units_tl
 %   }
 %   Options for products.
@@ -959,18 +1162,24 @@
 \tl_new:N \l_@@_units_tl
 \keys_define:nn { siunitx }
   {
+    product-close-bracket .tl_set:N =
+      \l_@@_bracket_close_tl ,
     product-exponents .choices:nn =
       { combine , combine-bracket , individual }
       { \tl_set_eq:NN \l_@@_exp_tl \l_keys_choice_tl } ,
+    product-independent-prefix .bool_set:N =
+      \l_@@_independent_bool ,
     product-mode .choice: ,
     product-mode / phrase .code:n =
       { \bool_set_true:N \l_@@_phrase_bool } ,
     product-mode / symbol .code:n =
       { \bool_set_false:N \l_@@_phrase_bool } ,
+    product-open-bracket .tl_set:N =
+      \l_@@_bracket_open_tl ,
     product-phrase .tl_set:N = \l_@@_phrase_tl ,
     product-symbol .tl_set:N = \l_@@_symbol_tl ,
     product-units .choices:nn =
-      { bracket , bracket-power , power , repeat , single }
+      { bracket , bracket-power , independent , power , repeat , single }
       { \tl_set_eq:NN \l_@@_units_tl \l_keys_choice_tl }
   }
 %    \end{macrocode}
@@ -1006,13 +1215,21 @@
   {
     \keys_set:nx { siunitx }
       {
-        compound-exponents       = \l_@@_exp_tl ,
-        compound-final-separator = { \exp_not:n {#1} } ,
-        compound-pair-separator  = { \exp_not:n {#1} } ,
-        compound-separator       = { \exp_not:n {#1} } ,
-        compound-separator-mode  =
+        compound-close-boundary       = ,
+        compound-close-bracket        =
+          { \exp_not:V \l_@@_bracket_close_tl } ,
+        compound-exponents            = \l_@@_exp_tl ,
+        compound-final-separator      = { \exp_not:n {#1} } ,
+        compound-independent-prefix =
+          \bool_if:NTF \l_@@_independent_bool { true } { false } ,
+        compound-open-boundary        = ,
+        compound-open-bracket         =
+          { \exp_not:V \l_@@_bracket_open_tl } ,
+        compound-pair-separator       = { \exp_not:n {#1} } ,
+        compound-separator            = { \exp_not:n {#1} } ,
+        compound-separator-mode       =
           \bool_if:NTF \l_@@_phrase_bool { text } { number } ,
-        compound-units           = \l_@@_units_tl
+        compound-units                = \l_@@_units_tl
       }
   }
 \cs_generate_variant:Nn \@@_aux:n { x }
@@ -1032,7 +1249,11 @@
 %
 % \begin{variable}
 %   {
+%     \l_@@_bracket_close_tl     ,
 %     \l_@@_exp_tl               ,
+%     \l_@@_independent_bool     ,
+%     \l_@@_bracket_open_tl      ,
+%     \l_@@_open_tl              ,
 %     \l_siunitx_range_phrase_tl ,
 %     \l_@@_units_tl
 %   }
@@ -1042,12 +1263,19 @@
 \tl_new:N \l_@@_units_tl
 \keys_define:nn { siunitx }
   {
+    range-close-bracket .tl_set:N =
+      \l_@@_bracket_close_tl ,
     range-exponents .choices:nn =
       { combine , combine-bracket , individual }
       { \tl_set_eq:NN \l_@@_exp_tl \l_keys_choice_tl } ,
+    range-independent-prefix .bool_set:N =
+      \l_@@_independent_bool ,
+    range-open-bracket .tl_set:N =
+      \l_@@_bracket_open_tl ,
+    range-open-phrase .tl_set:N = \l_@@_open_tl ,
     range-phrase .tl_set:N = \l_siunitx_range_phrase_tl ,
     range-units .choices:nn =
-      { bracket , repeat , single }
+      { bracket , independent , repeat , single }
       { \tl_set_eq:NN \l_@@_units_tl \l_keys_choice_tl }
   }
 %    \end{macrocode}
@@ -1076,10 +1304,20 @@
   {
     \keys_set:nx { siunitx }
       {
-        compound-exponents       = \l_@@_exp_tl ,
-        compound-pair-separator  = { \exp_not:V \l_siunitx_range_phrase_tl } ,
-        compound-separator-mode  = text ,
-        compound-units           = \l_@@_units_tl
+        compound-boundary-mode        = text ,
+        compound-close-boundary       = ,
+        compound-close-bracket        =
+          { \exp_not:V \l_@@_bracket_close_tl } ,
+        compound-exponents            = \l_@@_exp_tl ,
+        compound-independent-prefix =
+          \bool_if:NTF \l_@@_independent_bool { true } { false } ,
+        compound-open-boundary        = { \exp_not:V \l_@@_open_tl } ,
+        compound-open-bracket         =
+          { \exp_not:V \l_@@_bracket_open_tl } ,
+        compound-pair-separator       =
+          { \exp_not:V \l_siunitx_range_phrase_tl } ,
+        compound-separator-mode       = text ,
+        compound-units                = \l_@@_units_tl
       }
   }
 %    \end{macrocode}
@@ -1095,57 +1333,73 @@
 %    \begin{macrocode}
 \keys_set:nn { siunitx }
   {
-    compound-exponents       = individual  ,
-    compound-final-separator =
+    compound-boundary-mode      = text          ,
+    compound-close-boundary     =               , % (
+    compound-close-bracket      = )             ,
+    compound-exponents          = individual    ,
+    compound-final-separator    =
       {
         \ifmmode \  \else \space \fi
         \text { and }
         \ifmmode \  \else \space \fi
       } ,
-    compound-pair-separator  =
+    compound-independent-prefix = false      ,
+    compound-open-boundary      =            ,
+    compound-open-bracket       = (          , % )
+    compound-pair-separator     =
       {
         \ifmmode \  \else \space \fi
         \text { and }
         \ifmmode \  \else \space \fi
       } ,
-    compound-separator       =
+    compound-separator          =
       { , \ifmmode \  \else \space \fi } ,
-    compound-separator-mode  = text        ,
-    compound-units           = repeat      ,
-    list-exponents           = individual  ,
-    list-final-separator     =
+    compound-separator-mode     = text       ,
+    compound-units              = repeat     , % (
+    list-close-bracket          = )          ,
+    list-exponents              = individual ,
+    list-final-separator        =
       {
         \ifmmode \  \else \space \fi
         \text { and }
         \ifmmode \  \else \space \fi
       } ,
-    list-pair-separator      =
+    list-independent-prefix     = false      ,
+    list-open-bracket           = (          , % )
+    list-pair-separator         =
       {
         \ifmmode \  \else \space \fi
         \text { and }
         \ifmmode \  \else \space \fi
       } ,
-    list-separator           =
+    list-separator              =
       { , \ifmmode \  \else \space \fi } ,
-    list-units               = repeat      ,
-    product-exponents        = individual  ,
-    product-mode             = symbol      ,
-    product-phrase           =
+    list-units                  = repeat     , % (
+    product-close-bracket       = )          ,
+    product-exponents           = individual ,
+    product-independent-prefix  = false      ,
+    product-mode                = symbol     ,
+    product-open-bracket        = (          , % )
+    product-phrase              =
       {
         \ifmmode \  \else \space \fi
         \text { by }
         \ifmmode \  \else \space \fi
       } ,
-    product-symbol           = \times      ,
-    product-units            = repeat      ,
-    range-exponents          = individual  ,
-    range-phrase             =
+    product-symbol             = \times      ,
+    product-units              = repeat      , % (
+    range-close-bracket        = )           ,
+    range-exponents            = individual  ,
+    range-independent-prefix   = false       ,
+    range-open-bracket         = (           , % )
+    range-open-phrase          =             ,
+    range-phrase               =
       {
         \ifmmode \  \else \space \fi
         \text { to }
         \ifmmode \  \else \space \fi
       } ,
-    range-units              = repeat
+    range-units                = repeat
   }
 %    \end{macrocode}
 %

Modified: trunk/Master/texmf-dist/source/latex/siunitx/siunitx-locale.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/siunitx/siunitx-locale.dtx	2023-07-31 20:11:33 UTC (rev 67779)
+++ trunk/Master/texmf-dist/source/latex/siunitx/siunitx-locale.dtx	2023-07-31 20:18:52 UTC (rev 67780)
@@ -108,6 +108,12 @@
         inter-unit-product    = \,     ,
         output-decimal-marker = { , }
       } ,
+    locale / IT .meta:n =
+      {
+        exponent-product      = \times ,
+        inter-unit-product    = \,     ,
+        output-decimal-marker = { , }
+      } ,
     locale / PL .meta:n =
       {
         exponent-product      = \cdot ,
@@ -150,6 +156,7 @@
   {
     \RequirePackage { translations }
     \DeclareTranslation { Catalan }    { and } { i }
+    \DeclareTranslation { Italian }    { and } { e }
     \DeclareTranslation { Portuguese } { and } { e }
     \DeclareTranslation { Slovene }    { and } { in }
     \DeclareTranslation { Brazilian }  { to~(numerical~range) } { a }
@@ -157,6 +164,7 @@
     \DeclareTranslation { English }    { to~(numerical~range) } { to }
     \DeclareTranslation { French }     { to~(numerical~range) } { à }
     \DeclareTranslation { German }     { to~(numerical~range) } { bis }
+    \DeclareTranslation { Italian }    { to~(numerical~range) } { a }
     \DeclareTranslation { Polish }     { to~(numerical~range) } { do }
     \DeclareTranslation { Portuguese } { to~(numerical~range) } { a }
     \DeclareTranslation { Slovene }    { to~(numerical~range) } { do }

Modified: trunk/Master/texmf-dist/source/latex/siunitx/siunitx-number.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/siunitx/siunitx-number.dtx	2023-07-31 20:11:33 UTC (rev 67779)
+++ trunk/Master/texmf-dist/source/latex/siunitx/siunitx-number.dtx	2023-07-31 20:18:52 UTC (rev 67780)
@@ -411,6 +411,12 @@
 %   \end{syntax}
 % \end{function}
 %
+% \begin{function}{input-uncertainty-divider}
+%   \begin{syntax}
+%     |input-uncertainty-divider| = \meta{tokens}
+%   \end{syntax}
+% \end{function}
+%
 % \begin{function}{minimum-decimal-digits}
 %   \begin{syntax}
 %     |minimum-decimal-digits| = \meta{min}
@@ -522,6 +528,18 @@
 %   The standard setting is |false|.
 % \end{function}
 %
+% \begin{function}{round-direction}
+%   \begin{syntax}
+%     |round-direction| = |down|\verb"|"|nearest|\verb"|"|up|
+%   \end{syntax}
+%   Choice which determines how values values are rounded. The setting
+%   |up| means that the value is always rounded away from zero, whereas the
+%   setting |down| means that the value will be rounded toward zero. The
+%   setting |nearest| means that the value will be rounded to the nearest
+%   (either up or down), taking account of the setting of |round-half|.
+%   The standard setting is |nearest|
+% \end{function}
+%
 % \begin{function}{round-half}
 %   \begin{syntax}
 %     |round-half| = |even|\verb"|"|up|
@@ -636,6 +654,18 @@
 %   |full| style is used. The standard setting is |compact|.
 % \end{function}
 %
+% \begin{function}{uncertainty-round-direction}
+%   \begin{syntax}
+%     |uncertainty-round-direction| = |down|\verb"|"|nearest|\verb"|"|up|
+%   \end{syntax}
+%   Choice which determines how uncertainty values are rounded. The setting
+%   |up| means that the uncertainty is always rounded away from zero, whereas
+%   the setting |down| means that the uncertainty will be rounded toward zero.
+%   The setting |nearest| means that the uncertainty will be rounded to the
+%   nearest (either up or down), taking account of the setting of |round-half|.
+%   The standard setting is |nearest|
+% \end{function}
+%
 % \begin{function}{uncertainty-separator}
 %   \begin{syntax}
 %     |uncertainty-separator| = \meta{separator}
@@ -776,6 +806,12 @@
 % containing an identifier, then zero or more brace groups which contain
 % the uncertainty data. In this release, the known uncertainty types are
 % \begin{itemize}
+%   \item \texttt{A}: An unsymmetrical uncertainty made up of two values.
+%     Each is stored as uncertainty in significant digits, with no radix point
+%     in the stored value. The two parts are stored within one brace group,
+%     within which are two brace groups: the first contains the positive
+%     component, the second the negative component. Neither component has a
+%     sign.
 %   \item \texttt{S}: A symmetrical statistical uncertainty made up of
 %     a single value. These are stored as uncertainty in significant digits,
 %     with no radix point in the stored value.
@@ -797,6 +833,7 @@
 %      \l_siunitx_number_input_exponent_tl   ,
 %      \l_@@_input_ignore_tl                 ,
 %      \l_@@_input_uncert_open_tl            ,
+%      \l_@@_input_uncert_divide_tl          ,
 %      \l_siunitx_number_input_sign_tl       ,
 %      \l_@@_input_uncert_sign_tl            ,
 %      \l_@@_explicit_decimal_bool           ,
@@ -838,6 +875,8 @@
               { \tl_put_right:Nn \l_siunitx_number_input_sign_tl {##1} }
           }
       } ,
+    input-uncertainty-divider .tl_set:N =
+      \l_@@_input_uncert_divide_tl ,
     parse-numbers .bool_set:N =
       \l_siunitx_number_parse_bool ,
     retain-explicit-decimal-marker .bool_set:N =
@@ -911,11 +950,21 @@
 %    \end{macrocode}
 % \end{variable}
 %
-% \begin{variable}{\l_@@_uncert_tl}
+% \begin{variable}
+%   {
+%     \l_@@_tolerance_tl     ,
+%     \l_@@_uncert_tl        ,
+%     \l_@@_uncert_offset_int,
+%     \l_@@_uncert_types_tl
+%   }
 %   To allow multiple uncertainties, we want to build this up as possibly
-%   multiple entries.
+%   multiple entries. For asymmetrical uncertainties/tolerances, we need
+%   an additional store.
 %    \begin{macrocode}
+\tl_new:N \l_@@_tolerance_tl
 \tl_new:N \l_@@_uncert_tl
+\int_new:N \l_@@_uncert_offset_int
+\tl_new:N \l_@@_uncert_types_tl
 %    \end{macrocode}
 % \end{variable}
 %
@@ -992,6 +1041,7 @@
     \group_begin:
       \tl_clear:N \l_@@_parsed_tl
       \tl_clear:N \l_@@_uncert_tl
+      \tl_clear:N \l_@@_uncert_types_tl
       \tl_map_inline:Nn \l_@@_input_ignore_tl
         {
           \token_if_macro:NT ##1
@@ -1576,7 +1626,6 @@
 \cs_new_protected:Npn \@@_parse_loop_main_uncert:NN #1#2
   {
     \@@_parse_loop_main_store:NNN #1 #2 \c_false_bool
-    \tl_clear:N \l_@@_uncert_tl
     \@@_parse_uncert:N
   }
 %    \end{macrocode}
@@ -1647,6 +1696,7 @@
   {
     \tl_clear:N \l_@@_flex_tl
     \tl_clear:N \l_@@_parsed_tl
+    \tl_clear:N \l_@@_uncert_tl
   }
 %    \end{macrocode}
 % \end{macro}
@@ -1695,8 +1745,13 @@
 %
 % \begin{macro}{\@@_parse_uncert:N}
 % \begin{macro}{\@@_parse_uncert:NNN}
-% \begin{macro}{\@@_parse_uncert_auxi:N, \@@_parse_uncert_auxii:N}
-% \begin{macro}{\@@_parse_uncert_auxii:}
+% \begin{macro}
+%   {
+%     \@@_parse_uncert_auxi:N  ,
+%     \@@_parse_uncert_auxii:N ,
+%     \@@_parse_uncert_auxiv:N
+%   }
+% \begin{macro}{\@@_parse_uncert_auxiv:}
 % \begin{macro}{\@@_parse_uncert_marker:}
 % \begin{macro}{\@@_parse_uncert_marker:nnn}
 % \begin{macro}{\@@_parse_uncert_marker:nnnw}
@@ -1703,6 +1758,8 @@
 % \begin{macro}{\@@_parse_uncert_marker:Nnnn}
 % \begin{macro}{\@@_parse_uncert_marker:w}
 % \begin{macro}{\@@_parse_uncert_marker:nnnnN}
+% \begin{macro}{\@@_parse_uncert_marker:nnnnnN}
+% \begin{macro}{\@@_parse_uncert_marker:nnnnnnN}
 % \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,
@@ -1754,7 +1811,7 @@
       {
         \tl_if_in:NnTF \l_siunitx_number_input_decimal_tl {#1}
           { \@@_parse_uncert_marker: }
-          { \@@_parse_loop_break:w }
+          { \@@_parse_uncert_auxiv:N #1 }
       }
   }
 \cs_new_protected:Npn \@@_parse_uncert_auxii:N #1
@@ -1764,7 +1821,7 @@
         \@@_parse_uncert_auxiii:
         \@@_parse_uncert_after:N
       }
-      { \@@_parse_loop_break:w }
+      { \@@_parse_uncert_auxiv:N #1 }
   }
 %    \end{macrocode}
 %   Deal with the closing bracket, which might leave us with nothing if there
@@ -1778,6 +1835,24 @@
       { \tl_set:Nn \l_@@_partial_tl { 0 } }
   }
 %    \end{macrocode}
+%   A common auxiliary for the case where the token is not a digit, a
+%   decimal mark or a closing parenthesis.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_parse_uncert_auxiv:N #1
+  {
+    \tl_if_empty:NTF \l_@@_tolerance_tl
+      {
+        \tl_if_in:NnTF \l_@@_input_uncert_divide_tl {#1}
+          {
+            \cs_set_eq:NN \l_@@_tolerance_tl \l_@@_partial_tl
+            \tl_clear:N \l_@@_partial_tl
+            \@@_parse_uncert:N
+          }
+          { \@@_parse_loop_break:w }
+      }
+      { \@@_parse_loop_break:w }
+  }
+%    \end{macrocode}
 %   Handling a decimal marker in the uncertainty is a bit tricky: we need to make
 %   sure it's valid. First, we need to be sure that the integer part of the captured
 %   uncertainty is not too long. Then we need to check that the decimal part is
@@ -1785,7 +1860,7 @@
 %   Both of these require data from the collected partial number,
 %   so we extract that first. Checking the decimal part needs the length of the
 %   not-yet-collected uncertainty. There may be one or more parts to that, so
-%   we have to grab p to the \emph{first} closing token to count the length:
+%   we have to grab up to the \emph{first} closing token to count the length:
 %   just grabbing everything only works if there is only a single uncertainty.
 %   We take protective steps against an entirely-missing closing token so that
 %   there is not an uncontrolled error.
@@ -1826,22 +1901,62 @@
 %   With the separated out main part and the current uncertainty part
 %   available, we can pad the main part if required then restart the
 %   collection of the uncertainty having thrown away the decimal marker
-%   and with the lengths lined up.
+%   and with the lengths lined up. To account for asymmetrical
+%   uncertainties, there is a bit of work in tracking.
 %    \begin{macrocode}
 \cs_new_protected:Npn \@@_parse_uncert_marker:nnnnN #1#2#3#4#5
   {
+    \tl_set:Nx \l_@@_tmp_tl { \tl_head:V \l_@@_input_uncert_divide_tl }
+    \tl_if_empty:NTF \l_@@_tmp_tl
+      { \@@_parse_uncert_marker:nnnnnN {#1} {#2} {#3} {#4} { } #5 }
+      {
+        \use:x
+          {
+            \cs_set_protected:Npn \exp_not:N \@@_parse_uncert_marker:w
+              ####1 \l_@@_tmp_tl ####2 \l_@@_tmp_tl ####3 \exp_not:N \q_stop
+              {
+                \exp_not:N \tl_if_blank:nTF {####2}
+                  {
+                    \@@_parse_uncert_marker:nnnnnN
+                      \exp_not:n { {#1} {#2} {#3} }
+                      {####1} { }
+                  }
+                  {
+                    \@@_parse_uncert_marker:nnnnnN
+                      \exp_not:n { {#1} {#2} {#3} }
+                      {####1} { \l_@@_tmp_tl ####2 }
+                  }
+                    \exp_not:N #5
+              }
+             \exp_not:N \@@_parse_uncert_marker:w #4
+               \l_@@_tmp_tl \l_@@_tmp_tl \exp_not:N \q_stop
+          }
+      }
+  }
+\cs_new_protected:Npn \@@_parse_uncert_marker:nnnnnN #1#2#3#4#5#6
+  {
+    \exp_args:Ne \@@_parse_uncert_marker:nnnnnnN
+      { \int_eval:n { \tl_count:n {#4} } }
+      {#1} {#2} {#3} {#4} {#5} #6
+  }
+\cs_new_protected:Npn \@@_parse_uncert_marker:nnnnnnN #1#2#3#4#5#6#7
+  {
+    \bool_lazy_and:nnF
+      { \tl_if_empty_p:N \l_@@_tolerance_tl }
+      { \tl_if_empty_p:N \l_@@_uncert_types_tl }
+      {
+        \int_compare:nNnF {#1} = \l_@@_uncert_offset_int
+          { \@@_parse_loop_break:w }
+      }
+    \int_set:Nn \l_@@_uncert_offset_int {#1}
     \tl_set:Nx \l_@@_parsed_tl
       {
-         {#1}
          {#2}
+         {#3}
          {
-           #3
+           #4
            \prg_replicate:nn
-             {
-               \int_max:nn
-                 { 0 }
-                 { \tl_count:n {#4} - \tl_count:n {#3} }
-             }
+             { \int_max:nn { 0 } { #1 - \tl_count:n {#4} } }
              { 0 }
          }
       }
@@ -1854,7 +1969,7 @@
         \@@_parse_uncert:NNN \c_true_bool
           \@@_parse_uncert_auxii:N
       }
-        #4#5
+        #5#6#7
   }
 %    \end{macrocode}
 %   At the end of collection, we can either start another one or be done:
@@ -1866,9 +1981,26 @@
       {
         \exp_not:V \l_@@_uncert_tl
         \tl_if_empty:NF \l_@@_partial_tl
-          { { \exp_not:V \l_@@_partial_tl } }
+          {
+            {
+              \tl_if_empty:NTF \l_@@_tolerance_tl
+                { \exp_not:V \l_@@_partial_tl }
+                {
+                  { \exp_not:V \l_@@_tolerance_tl }
+                  { \exp_not:V \l_@@_partial_tl }
+                }
+              }
+          }
       }
+    \tl_set:Nx \l_@@_uncert_types_tl
+      {
+        \l_@@_uncert_types_tl
+        \tl_if_empty:NTF \l_@@_tolerance_tl
+          { S }
+          { A }
+      }
     \tl_clear:N \l_@@_partial_tl
+    \tl_clear:N \l_@@_tolerance_tl
     \quark_if_recursion_tail_stop_do:Nn #1
       {
         \tl_set:Nx \l_@@_parsed_tl
@@ -1877,11 +2009,7 @@
             {
               \tl_if_empty:NF \l_@@_uncert_tl
                 {
-                  {
-                    \prg_replicate:nn
-                      { \tl_count:N \l_@@_uncert_tl }
-                     { S }
-                  }
+                  { \l_@@_uncert_types_tl }
                   \exp_not:V \l_@@_uncert_tl
                 }
             }
@@ -1888,6 +2016,7 @@
           }
         \tl_clear:N \l_@@_partial_tl
         \tl_clear:N \l_@@_uncert_tl
+        \int_zero:N \l_@@_uncert_offset_int
       }
     \tl_if_in:NnTF \l_@@_input_uncert_open_tl {#1}
       { \@@_parse_uncert:N }
@@ -1905,6 +2034,8 @@
 % \end{macro}
 % \end{macro}
 % \end{macro}
+% \end{macro}
+% \end{macro}
 %
 % \subsection{Processing numbers}
 %
@@ -1917,11 +2048,13 @@
 %     \l_@@_exponent_fixed_int     ,
 %     \l_@@_min_decimal_int        ,
 %     \l_@@_min_integer_int        ,
+%     \l_@@_round_dir_tl           ,
 %     \l_@@_round_half_even_bool   ,
 %     \l_@@_round_mode_tl          ,
 %     \l_@@_round_pad_bool         ,
 %     \l_@@_round_precision_int    ,
-%     \l_@@_round_positive_bool
+%     \l_@@_round_positive_bool    ,
+%     \l_@@_round_uncert_dir_tl
 %   }
 %    \begin{macrocode}
 \keys_define:nn { siunitx }
@@ -1943,6 +2076,9 @@
       \l_@@_min_decimal_int ,
     minimum-integer-digits .int_set:N =
       \l_@@_min_integer_int ,
+    round-direction .choices:nn =
+      { down , nearest , up }
+      { \tl_set_eq:NN \l_@@_round_dir_tl \l_keys_choice_tl } ,
     round-half .choice: ,
     round-half / even .code:n =
       { \bool_set_true:N \l_@@_round_half_even_bool } ,
@@ -1958,11 +2094,16 @@
     round-precision .int_set:N =
       \l_@@_round_precision_int ,
     round-zero-positive .bool_set:N =
-      \l_@@_round_positive_bool
+      \l_@@_round_positive_bool ,
+    uncertainty-round-direction .choices:nn =
+      { down , nearest , up }
+      { \tl_set_eq:NN \l_@@_round_uncert_dir_tl \l_keys_choice_tl } ,
   }
 \bool_new:N \l_@@_round_half_even_bool
 \tl_new:N \l_@@_exponent_mode_tl
+\tl_new:N \l_@@_round_dir_tl
 \tl_new:N \l_@@_round_mode_tl
+\tl_new:N \l_@@_round_uncert_dir_tl
 %    \end{macrocode}
 % \end{variable}
 %
@@ -2611,15 +2752,16 @@
 % \end{macro}
 %
 % \begin{macro}[EXP]{\@@_round:nnn, \@@_round:fnn}
+% \begin{macro}[EXP]{\@@_round:nnnn, \@@_round:Vnnn}
 % \begin{macro}[EXP]
 %   {
-%     \@@_round_auxi:nnnN  ,
-%     \@@_round_auxii:nnnN ,
-%     \@@_round_auxiii:nnnN
+%     \@@_round_auxi:nnnnN   ,
+%     \@@_round_auxii:nnnnN  ,
+%     \@@_round_auxiii:nnnnN ,
+%     \@@_round_auxiv:nnnnN
 %   }
-%  \begin{macro}[EXP]{\@@_round_auxiv:nnN, \@@_round_auxv:nnN}
-%  \begin{macro}[EXP]{\@@_round_auxvi:nN}
-%  \begin{macro}[EXP]{\@@_round_auxvii:nnTF}
+%  \begin{macro}[EXP]{\@@_round_auxv:nnnN, \@@_round_auxvi:nnnN}
+%  \begin{macro}[EXP]{\@@_round_auxvii:nnnTF}
 %  \begin{macro}[EXP]{\@@_round_auxviii:nnN, \@@_round_auxix:nnN}
 %  \begin{macro}[EXP]{\@@_round_final_integer:nnw, \@@_round_final_decimal:nnw}
 %  \begin{macro}[EXP]{\@@_round_final_signicant:n}
@@ -2648,34 +2790,40 @@
 %    \begin{macrocode}
 \cs_new:Npn \@@_round:nnn #1#2#3
   {
-    \@@_round_auxi:nnnN {#1} {#2} { }
-      #3 \q_recursion_tail \q_recursion_stop
+    \@@_round:Vnnn \l_@@_round_dir_tl
+      {#1} {#2} {#3}
   }
 \cs_generate_variant:Nn \@@_round:nnn { f }
-\cs_new:Npn \@@_round_auxi:nnnN #1#2#3#4
+\cs_new:Npn \@@_round:nnnn #1#2#3#4
   {
-    \quark_if_recursion_tail_stop_do:Nn #4
+    \@@_round_auxi:nnnnN {#1} {#2} {#3} { }
+      #4 \q_recursion_tail \q_recursion_stop
+  }
+\cs_generate_variant:Nn \@@_round:nnnn { V }
+\cs_new:Npn \@@_round_auxi:nnnnN #1#2#3#4#5
+  {
+    \quark_if_recursion_tail_stop_do:Nn #5
       {
-        \@@_round_auxii:nnnN {#1} {#3} { } #2
+        \@@_round_auxii:nnnnN {#1} {#2} {#4} { } #3
           \q_recursion_tail \q_recursion_stop
       }
-    \@@_round_auxi:nnnN {#1} {#2} {#4#3}
+    \@@_round_auxi:nnnnN {#1} {#2} {#3} {#5#4}
   }
-\cs_new:Npn \@@_round_auxii:nnnN #1#2#3#4
+\cs_new:Npn \@@_round_auxii:nnnnN #1#2#3#4#5
   {
-    \quark_if_recursion_tail_stop_do:Nn #4
+    \quark_if_recursion_tail_stop_do:Nn #5
       {
-        \tl_if_blank:nTF {#2}
+        \tl_if_blank:nTF {#3}
           {
-            \@@_round_auxiv:nnnN {#1} { } { } #3
+            \@@_round_auxiv:nnnnN {#2} {#1} { } { } #4
               \q_recursion_tail \q_recursion_stop
           }
           {
-            \@@_round_auxiii:nnnN {#1} {#3} { } #2
+            \@@_round_auxiii:nnnnN {#2} {#1} {#4} { } #3
               \q_recursion_tail \q_recursion_stop
           }
       }
-    \@@_round_auxii:nnnN {#1} {#2} {#4#3}
+    \@@_round_auxii:nnnnN {#1} {#2} {#3} {#5#4}
   }
 %    \end{macrocode}
 %   We now have the input reversed plus how many digits we need to discard
@@ -2688,27 +2836,27 @@
 %   of the integer: that may product a value of $1\dots$: we tidy up the
 %   case where it comes out as $0$ later.
 %    \begin{macrocode}
-\cs_new:Npn \@@_round_auxiii:nnnN #1#2#3#4
+\cs_new:Npn \@@_round_auxiii:nnnnN #1#2#3#4#5
   {
-    \quark_if_recursion_tail_stop_do:Nn #4
+    \quark_if_recursion_tail_stop_do:Nn #5
       {
-        \@@_round_auxiv:nnnN {#1} { } {#3} #2
+        \@@_round_auxiv:nnnnN {#1} {#2} { } {#4} #3
           \q_recursion_tail \q_recursion_stop
       }
     \int_compare:nNnTF {#1} > 0
       {
-        \exp_args:Nf \@@_round_auxiii:nnnN
-          { \int_eval:n { #1 - 1 } } {#2} { #4#3 }
+        \exp_args:Nf \@@_round_auxiii:nnnnN
+          { \int_eval:n { #1 - 1 } } {#2} {#3} { #5#4 }
       }
-      { \@@_round_auxv:nnN {#3} {#2} #4 }
+      { \@@_round_auxv:nnnN {#2} {#4} {#3} #5 }
   }
-\cs_new:Npn \@@_round_auxiv:nnnN #1#2#3#4
+\cs_new:Npn \@@_round_auxiv:nnnnN #1#2#3#4#5
   {
-    \quark_if_recursion_tail_stop_do:Nn #4
+    \quark_if_recursion_tail_stop_do:Nn #5
       {
         \int_compare:nNnTF {#1} = 0
           {
-            \@@_round_auxvi:nnN {#3} {#2}
+            \@@_round_auxvi:nnnN {#2} {#4} {#3}
               0 \q_recursion_tail \q_recursion_stop
           }
           { { 0 } { } }
@@ -2715,47 +2863,60 @@
       }
     \int_compare:nNnTF {#1} > 0
       {
-        \exp_args:Nf \@@_round_auxiv:nnnN
-          { \int_eval:n { #1 - 1 } } { #2 0 } { #4#3 }
+        \exp_args:Nf \@@_round_auxiv:nnnnN
+          { \int_eval:n { #1 - 1 } } {#2} { #3 0 } { #5#4 }
       }
-      { \@@_round_auxvi:nnN {#3} {#2} #4 }
+      { \@@_round_auxvi:nnnN {#2} {#4} {#3} #5 }
   }
 %    \end{macrocode}
-%   The lead off to rounding proper needs to deal with the half-even rule:
-%   it can only apply at this stage, when the \emph{discarded} value can
-%   be exactly half.
+%   We now have the discarded digits, the matching filler and the
+%   next digit. So we can make the decision on rounding: that
+%   is handled by a common auxiliary.
 %    \begin{macrocode}
-\cs_new:Npn \@@_round_auxv:nnN #1#2#3
+\cs_new:Npn \@@_round_auxv:nnnN #1#2#3#4
   {
-    \quark_if_recursion_tail_stop_do:Nn #3
+    \quark_if_recursion_tail_stop_do:Nn #4
       {
-        \@@_round_auxvi:nnN
-          {#1} { } #2 \q_recursion_tail \q_recursion_stop
+        \@@_round_auxvi:nnnN
+          {#1} {#2} { } #3 \q_recursion_tail \q_recursion_stop
       }
-    \@@_round_auxvii:nnTF {#1} {#3}
+    \@@_round_auxvii:nnnTF {#1} {#2} {#4}
       { \@@_round_final_decimal:nnw }
       { \@@_round_auxviii:nnN }
-        {#2} { } #3
+        {#3} { } #4
   }
-\cs_new:Npn \@@_round_auxvi:nnN #1#2#3
+\cs_new:Npn \@@_round_auxvi:nnnN #1#2#3#4
   {
-    \quark_if_recursion_tail_stop_do:Nn #3
+    \quark_if_recursion_tail_stop_do:Nn #4
       { { 0 } { } }
-    \@@_round_auxvii:nnTF {#1} {#3}
+    \@@_round_auxvii:nnnTF {#1} {#2} {#4}
       { \@@_round_final_integer:nnw }
       { \@@_round_auxix:nnN }
-        { } {#2} #3
+        { } {#3} #4
   }
-\cs_new:Npn \@@_round_auxvii:nnTF #1#2
+%    \end{macrocode}
+%   For rounding up or down, the decision here is easy: pick the appropriate
+%   branch. For rounding to nearest, we need to deal with the half-even rule:
+%   it can only apply at this stage, when the \emph{discarded} value can
+%   be exactly half.
+%    \begin{macrocode}
+\cs_new:Npn \@@_round_auxvii:nnnTF #1#2#3
   {
-    \bool_lazy_or:nnTF
-      { \int_compare_p:nNn { 0 \tl_head:n {#1} } < 5 }
+    \str_case:nnF {#1}
       {
-        \bool_lazy_all_p:n
+        { down } { \use_i:nn }
+        { up }   { \use_ii:nn }
+      }
+      {
+        \bool_lazy_or:nnTF
+          { \int_compare_p:nNn { 0 \tl_head:n {#2} } < 5 }
           {
-            { \l_@@_round_half_even_bool }
-            { ! \int_if_odd_p:n {#2} }
-            { \@@_round_if_half_p:n {#1} }
+            \bool_lazy_all_p:n
+              {
+                { \l_@@_round_half_even_bool }
+                { ! \int_if_odd_p:n {#3} }
+                { \@@_round_if_half_p:n {#2} }
+              }
           }
       }
   }
@@ -3271,8 +3432,9 @@
     \use:e
       {
         \exp_not:N \@@_round_uncertainty:nnnnnn
-          \@@_round:nnn {#1} { } {#4}
-          {#2} {#3} {#1} {#4}
+          \@@_round:Vnnn
+            \l_@@_round_uncert_dir_tl {#1} { } {#4}
+            {#2} {#3} {#1} {#4}
       }
   }
 %    \end{macrocode}
@@ -4240,6 +4402,7 @@
   \@@_output_uncert_A:nnnn
 \cs_new:Npx \@@_output_uncert_A:nnnnn #1#2#3#4#5
   {
+    { }
     ^
       { 
         +
@@ -4631,6 +4794,7 @@
     retain-explicit-plus             = false                                  ,
     retain-negative-zero             = false                                  ,
     retain-zero-uncertainty          = false                                  ,
+    round-direction                  = nearest                                ,
     round-half                       = up                                     ,
     round-minimum                    = 0                                      ,
     round-mode                       = none                                   ,
@@ -4642,15 +4806,19 @@
     uncertainty-descriptor-separator = \                                      ,
     uncertainty-descriptors          =                                        ,
     uncertainty-mode                 = compact                                ,
+    uncertainty-round-direction      = nearest                                ,
     uncertainty-separator            =                                        ,
     zero-decimal-as-symbol           = false                                  ,
     zero-symbol                      = \mbox { --- }
   }
 %    \end{macrocode}
-%   One awkward setting.
+%   Two awkward settings.
 %    \begin{macrocode}
 \keys_set:nx { siunitx }
-   { exponent-thresholds = -3 \c_colon_str 3 }
+  {
+    exponent-thresholds       = -3 \c_colon_str 3 ,
+    input-uncertainty-divider = \c_colon_str
+  }
 %    \end{macrocode}
 %
 %    \begin{macrocode}

Modified: trunk/Master/texmf-dist/source/latex/siunitx/siunitx-table.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/siunitx/siunitx-table.dtx	2023-07-31 20:11:33 UTC (rev 67779)
+++ trunk/Master/texmf-dist/source/latex/siunitx/siunitx-table.dtx	2023-07-31 20:18:52 UTC (rev 67780)
@@ -190,6 +190,15 @@
 %   the same size.
 % \end{function}
 %
+% \begin{function}{table-model-setup}
+%   \begin{syntax}
+%     |table-model-setup| = \meta{commands}
+%   \end{syntax}
+%   Additional commands to be inserted when using the |table-format| to
+%   create a model for alignment of cells. Typically this will be used to
+%   handle variable-width fonts in columns. The standard setting is empty.
+% \end{function}
+%
 % \begin{function}{table-number-alignment}
 %   \begin{syntax}
 %     |table-number-alignment| = |center|\verb"|"|left|\verb"|"|right|
@@ -818,7 +827,12 @@
 % \end{macro}
 %
 % \begin{variable}
-%   {\l_@@_auto_round_bool, \l_@@_align_mode_tl, \l_@@_align_number_tl}
+%   {
+%     \l_@@_auto_round_bool,
+%     \l_@@_model_setup_tl ,
+%     \l_@@_align_mode_tl  ,
+%     \l_@@_align_number_tl
+%   }
 %   Options for tables with defined space.
 %    \begin{macrocode}
 \keys_define:nn { siunitx }
@@ -842,6 +856,8 @@
         \exp_args:NV \@@_generate_model:n \l_@@_model_tl
         \tl_set:Nn \l_@@_align_mode_tl { format }
       } ,
+    table-model-setup .tl_set:N =
+      \l_@@_model_setup_tl ,
     table-number-alignment .choices:nn =
       { center , left , right }
       { \tl_set_eq:NN \l_@@_align_number_tl \l_keys_choice_tl }
@@ -1174,7 +1190,12 @@
 %     \@@_print_format_auxxii:w  ,
 %     \@@_print_format_auxxiii:w
 %   }
-% \begin{macro}{\@@_print_format_box:Nn}
+% \begin{macro}
+%   {
+%     \@@_print_format_box:Nn, \@@_print_format_box:No ,
+%     \@@_print_model_box:Nn, \@@_print_model_box:No
+%   }
+% \begin{macro}{\@@_print_format_box:nNn, \@@_print_format_box:VNn}
 % \begin{macro}{\@@_print_format_after:N}
 % \begin{macro}{\@@_print_none:nnn}
 %    \begin{macrocode}
@@ -1325,7 +1346,7 @@
   #1 \q_nil #2 \q_mark #3 \q_nil #4 \q_stop
   {
     \@@_color_check:w #3 \q_nil \q_stop
-    \@@_print_format_box:Nn \l_@@_tmp_box {#1}
+    \@@_print_model_box:Nn \l_@@_tmp_box {#1}
     \bool_if:NTF \l_@@_align_before_bool
       {
         \hbox_set_to_wd:Nnn \l_@@_integer_box
@@ -1365,7 +1386,7 @@
 \cs_new_protected:Npn \@@_print_format_auxii:w
   #1 \q_nil #2 \q_nil #3 \q_mark #4 \q_nil #5 \q_nil #6 \q_stop
   {
-    \@@_print_format_box:Nn \l_@@_tmp_box {#1#2}
+    \@@_print_model_box:Nn \l_@@_tmp_box {#1#2}
     \dim_set:Nn \l_@@_tmp_dim { \box_wd:N \l_@@_tmp_box }
     \@@_print_format_box:Nn \l_@@_tmp_box {#4#5}
     \dim_compare:nNnT { \box_wd:N \l_@@_tmp_box } > \l_@@_tmp_dim
@@ -1425,19 +1446,20 @@
         \@@_fil:
         \hbox_unpack:N \l_@@_before_box
       }
-    \@@_print_format_auxiii:w #3 \q_mark #6 \q_stop
+    \@@_print_format_auxiii:w ? #3 \q_mark ? #6 \q_stop
   }
 %    \end{macrocode}
 %   We now deal with the decimal part: there is nothing already in the
 %   |decimal| box, so the basics are easy. We need to \enquote{carry forward}
 %   any white space, as where it gets inserted depends on the options for
-%   subsequent parts.
+%   subsequent parts. The \cs{use_none:n} here remove the two |?| above:
+%   those are added to preserve braces around the decimal marker.
 %    \begin{macrocode}
 \cs_new_protected:Npn \@@_print_format_auxiii:w
   #1 \q_nil #2 \q_nil #3 \q_mark #4 \q_nil #5 \q_nil #6 \q_stop
   {
-    \@@_print_format_box:Nn \l_@@_tmp_box {#1#2}
-    \@@_print_format_box:Nn \l_@@_decimal_box {#4#5}
+    \@@_print_model_box:No \l_@@_tmp_box { \use_none:n #1#2 }
+    \@@_print_format_box:No \l_@@_decimal_box { \use_none:n #4#5 }
     \dim_set:Nn \l_@@_carry_dim
       {
           \box_wd:N \l_@@_tmp_box
@@ -1505,7 +1527,7 @@
   #1 \q_nil #2 \q_nil #3 \q_mark
   #4 \q_nil #5 \q_nil #6 \q_stop
   {
-    \@@_print_format_box:Nn \l_@@_tmp_box {#1#2}
+    \@@_print_model_box:Nn \l_@@_tmp_box {#1#2}
     \hbox_set_to_wd:Nnn \l_@@_tmp_box
       {
           \box_wd:N \l_@@_uncert_box
@@ -1535,7 +1557,7 @@
   #1 \q_nil #2 \q_mark
   #3 \q_nil #4 \q_stop
   {
-    \@@_print_format_box:Nn \l_@@_tmp_box { { } #1 }
+    \@@_print_model_box:Nn \l_@@_tmp_box { { } #1 }
     \dim_set:Nn \l_@@_tmp_dim { \box_wd:N \l_@@_tmp_box }
     \@@_print_format_box:Nn \l_@@_tmp_box { { } #3 }
     \@@_print_format_auxxii:w #2 \q_mark #4 \q_stop
@@ -1562,7 +1584,7 @@
   {
     \tl_if_blank:nF {#2}
       {
-        \@@_print_format_box:Nn \l_@@_tmp_box { { } #1#2 }
+        \@@_print_model_box:Nn \l_@@_tmp_box { { } #1#2 }
         \dim_set:Nn \l_@@_tmp_dim { \box_wd:N \l_@@_tmp_box }
         \@@_print_format_box:Nn \l_@@_tmp_box
           {
@@ -1570,7 +1592,7 @@
               { \l_@@_align_exponent_bool }
               { \tl_if_blank_p:n {#3} }
               {
-                \@@_print_format_box:Nn \l_@@_tmp_box { { } #1 { } }
+                \@@_print_model_box:Nn \l_@@_tmp_box { { } #1 { } }
                 \@@_skip:n { \box_wd:N \l_@@_tmp_box }
               }
             { } #3#4
@@ -1580,16 +1602,27 @@
   }
 %    \end{macrocode}
 %   A simple auxiliary to avoid relatively expensive use of the print routine
-%   for empty parts.
+%   for empty parts. There is a separate function for the model as this allows
+%   for the case where different font widths are in use.
 %    \begin{macrocode}
 \cs_new_protected:Npn \@@_print_format_box:Nn #1#2
+  { \@@_print_format_box:nNn { } #1 {#2} }
+\cs_generate_variant:Nn \@@_print_format_box:Nn { No }
+\cs_new_protected:Npn \@@_print_model_box:Nn #1#2
+  { \@@_print_format_box:VNn \l_@@_model_setup_tl #1 {#2}  }
+\cs_generate_variant:Nn \@@_print_model_box:Nn { No }
+\cs_new_protected:Npn \@@_print_format_box:nNn #1#2#3
   {
-    \hbox_set:Nn #1
+    \hbox_set:Nn #2
       {
-        \tl_if_blank:nF {#2}
-          { \siunitx_print_number:n {#2} }
+        \tl_if_blank:nF {#3}
+          {
+            #1
+            \siunitx_print_number:n {#3}
+          }
       }
   }
+\cs_generate_variant:Nn \@@_print_format_box:nNn { V }
 %    \end{macrocode}
 %   A common routine for placing material after the decimal marker and
 %   \enquote{shuffling}.
@@ -1653,6 +1686,7 @@
 % \end{macro}
 % \end{macro}
 % \end{macro}
+% \end{macro}
 %
 % \subsection{Standard settings for module options}
 %

Modified: trunk/Master/texmf-dist/source/latex/siunitx/siunitx.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/siunitx/siunitx.dtx	2023-07-31 20:11:33 UTC (rev 67779)
+++ trunk/Master/texmf-dist/source/latex/siunitx/siunitx.dtx	2023-07-31 20:18:52 UTC (rev 67780)
@@ -122,7 +122,7 @@
 %
 % Identify the package and give the over all version information.
 %    \begin{macrocode}
-\ProvidesExplPackage {siunitx} {2023-07-26} {3.2.9}
+\ProvidesExplPackage {siunitx} {2023-07-31} {3.3.0}
   {A comprehensive (SI) units package}
 %    \end{macrocode}
 %
@@ -184,16 +184,22 @@
 %
 % \subsection{Load time options}
 %
-% \begin{variable}{\l_@@_column_type_tl}
+% \begin{variable}{\l_@@_list_tl, \l_@@_product_tl, \l_@@_column_type_tl}
 %    \begin{macrocode}
 \keys_define:nn { siunitx }
   {
+    list-input-separator .tl_set:N =
+      \l_@@_list_tl ,
+    product-input-separator .tl_set:N =
+      \l_@@_product_tl ,
     table-column-type .tl_set:N =
       \l_@@_column_type_tl
   }
 \keys_set:nn { siunitx }
   {
-    table-column-type = S
+    list-input-separator    = ; ,
+    product-input-separator = x ,
+    table-column-type       = S
   }
 %    \end{macrocode}
 % \end{variable}
@@ -257,7 +263,11 @@
 %    \begin{macrocode}
 \IfFormatAtLeastTF { 2020-10-01 }
   { }
-  { \RequirePackage { xparse } }
+  {
+    \RequirePackage { xparse }
+    \providecommand \ExpandArgs [1]
+      { \cs_if_exist_use:c { exp_args:N #1 } }
+  }
 %    \end{macrocode}
 %
 % \subsubsection{Preamble commands}
@@ -375,9 +385,13 @@
 %   {\qtylist, \numlist, \qtyproduct, \numproduct, \qtyrange, \numproduct}
 %   Interfaces for compound values.
 %    \begin{macrocode}
-\NewDocumentCommand \qtylist
-  { O { } > { \SplitList { ; } } m > { \TrimSpaces } m }
+\ExpandArgs { Ne } \NewDocumentCommand \qtylist
   {
+    O { }
+    > { \SplitList { \exp_not:V \l_@@_list_tl } } m
+    > { \TrimSpaces } m
+  }
+  {
     \mode_leave_vertical:
     \group_begin:
       \siunitx_unit_options_apply:n {#3}
@@ -385,8 +399,12 @@
       \siunitx_quantity_list:nn {#2} {#3}
     \group_end:
   }
-\NewDocumentCommand \numlist { O { } > { \SplitList { ; } } m }
+\ExpandArgs { Ne } \NewDocumentCommand \numlist
   {
+    O { }
+    > { \SplitList { \exp_not:V \l_@@_list_tl } } m
+  }
+  {
     \mode_leave_vertical:
     \group_begin:
       \keys_set:nn { siunitx } {#1}
@@ -393,9 +411,13 @@
       \siunitx_number_list:nn {#2}
     \group_end:
   }
-\NewDocumentCommand \qtyproduct
-  { O { } > { \SplitList { x } } m > { \TrimSpaces } m }
+\ExpandArgs { Ne } \NewDocumentCommand \qtyproduct
   {
+    O { }
+    > { \SplitList { \exp_not:V \l_@@_product_tl } } m
+    > { \TrimSpaces } m
+  }
+  {
     \mode_leave_vertical:
     \group_begin:
       \siunitx_unit_options_apply:n {#3}
@@ -403,9 +425,12 @@
       \siunitx_quantity_product:nn {#2} {#3}
     \group_end:
   }
-\NewDocumentCommand \numproduct
-  { O { } > { \SplitList { x } } > { \TrimSpaces } m }
+\ExpandArgs { Ne } \NewDocumentCommand \numproduct
   {
+    O { }
+    > { \SplitList { \exp_not:V \l_@@_product_tl } } m
+  }
+  {
     \mode_leave_vertical:
     \group_begin:
       \keys_set:nn { siunitx } {#1}
@@ -435,12 +460,9 @@
 % \begin{macro}{\complexnum, \complexqty}
 %   Interfaces for complex numbers.
 %    \begin{macrocode}
-\use:e
+\ExpandArgs { Ne } \NewDocumentCommand \complexnum
+  { O { } > { \SplitArgument { 1 } { \c_colon_str } } m }
   {
-    \NewDocumentCommand \exp_not:N \complexnum
-      { O { } > { \SplitArgument { 1 } { \c_colon_str } } m }
-  }
-  {
     \mode_leave_vertical:
     \group_begin:
       \keys_set:nn { siunitx } {#1}
@@ -447,12 +469,9 @@
       \@@_complex_number_aux:nn #2
     \group_end:
   }
-\use:e
+\ExpandArgs { Ne } \NewDocumentCommand \complexqty
+  { O { } > { \SplitArgument { 1 } { \c_colon_str } } m  m }
   {
-    \NewDocumentCommand \exp_not:N \complexqty
-      { O { } > { \SplitArgument { 1 } { \c_colon_str } } m  m }
-  }
-  {
     \mode_leave_vertical:
     \group_begin:
       \siunitx_unit_options_apply:n {#3}

Modified: trunk/Master/texmf-dist/source/latex/siunitx/siunitx.ins
===================================================================
--- trunk/Master/texmf-dist/source/latex/siunitx/siunitx.ins	2023-07-31 20:11:33 UTC (rev 67779)
+++ trunk/Master/texmf-dist/source/latex/siunitx/siunitx.ins	2023-07-31 20:18:52 UTC (rev 67780)
@@ -81,11 +81,11 @@
     \file{siunitx.sty}
       {%
         \from{siunitx.dtx}             {package,init}
+        \from{siunitx-number.dtx}      {package}
         \from{siunitx-angle.dtx}       {package}
         \from{siunitx-complex.dtx}     {package}
         \from{siunitx-compound.dtx}    {package}
         \from{siunitx-locale.dtx}      {package}
-        \from{siunitx-number.dtx}      {package}
         \from{siunitx-print.dtx}       {package}
         \from{siunitx-table.dtx}       {package}
         \from{siunitx-unit.dtx}        {package}

Modified: trunk/Master/texmf-dist/source/latex/siunitx/siunitx.tex
===================================================================
--- trunk/Master/texmf-dist/source/latex/siunitx/siunitx.tex	2023-07-31 20:11:33 UTC (rev 67779)
+++ trunk/Master/texmf-dist/source/latex/siunitx/siunitx.tex	2023-07-31 20:18:52 UTC (rev 67780)
@@ -1,6 +1,6 @@
 \iffalse meta-comment
 
-File: siunitx.tex Copyright (C) 2014-2022 Joseph Wright
+File: siunitx.tex Copyright (C) 2014-2023 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
@@ -640,9 +640,9 @@
       \DescribePrefix{hecto}  &   2 \\
       \DescribePrefix{yocto}  & -24 &
       \DescribePrefix{kilo}   &   3 \\
+      \DescribePrefix{zepto}  & -21 &
+      \DescribePrefix{mega}   &   6 \\
       \DescribePrefix{atto}   & -18 &
-      \DescribePrefix{mega}   &   6 \\
-      \DescribePrefix{zepto}  & -21 &
       \DescribePrefix{giga}   &   9 \\
       \DescribePrefix{femto}  & -15 &
       \DescribePrefix{tera}   &  12 \\
@@ -883,6 +883,12 @@
 
       \midrule
 
+      \DescribeUnit[tesla]{T}       \\
+      \DescribeUnit[millitesla]{mT} \\
+      \DescribeUnit[microtesla]{uT} \\
+
+      \midrule
+
       \DescribeUnit[kelvin]{K} \\
 
       \midrule
@@ -1305,6 +1311,7 @@
       input-ignore                   & Literal & \meta{none}      \\
       input-open-uncertainty         & Literal & (                \\ ^^A )
       input-signs                    & Literal & +-\cs{pm}\cs{mp} \\
+      input-uncertainty-divider      & Literal & :                \\
       input-uncertainty-signs        & Literal & \cs{pm}          \\
       parse-numbers                  & Switch  & true             \\
       retain-explicit-decimal-marker & Switch  & false            \\
@@ -1364,18 +1371,38 @@
 decimal marker in \enquote{compact} form. These are treated as equivalent by
 the code.\footnote{The package author favors the form without a decimal marker,
 and formal guidance is ambiguous on which is correct. The form with a decimal
-marker is seen in for example some \acro{NIST} publications.}
+marker is seen in for example some \acro{NIST} publications.} Where multiple
+uncertainty values cross the decimal marker, they should all have the same
+number of digits.
 \begin{LaTeXdemo}
   \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.
+Multiple symmetrical 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{input-uncertainty-divider}
+In some areas, uncertainties (or tolerances) are given in an asymmetric format.
+This is supported in the \enquote{compact} input form in \pkg{siunitx}, with
+the positive and negative parts of the uncertainty divided by a symbol listed
+in \opt{input-uncertainty-divider}. When given in this divided form, the
+two parts are interpreted as first the positive and then the negative
+component. Asymmetric uncertainties which cross the decimal marker are
+supported provided both components have the same number of digits.
+\begin{LaTeXdemo}
+  \num{10.56(12:34)} \\
+  \num{123.4(4.6:7.8)}
+\end{LaTeXdemo}
+Symmetrical and asymmetrical uncertainties may be intermixed.
+\begin{LaTeXdemo}
+  \num{10.56(1:2)(3)} \\
+  \num{6.45(2)(3:4)}
+\end{LaTeXdemo}
+
 \DescribeOption{parse-numbers}
 The \opt{parse-numbers} option turns the entire parsing system on and off. The
 option is made available for two reasons. First, if all of the numbers in a
@@ -1445,20 +1472,22 @@
       Type &
       \multicolumn{1}{l@{}}{Default} \\
     \midrule
-      drop-exponent            & Switch  & false \\
-      drop-uncertainty         & Switch  & false \\
-      drop-zero-decimal        & Switch  & false \\
-      exponent-mode            & Switch  & input \\
-      exponent-thresholds      & Literal & -3:3  \\
-      fixed-exponent           & Integer & 0     \\
-      minimum-integer-digits   & Integer & 0     \\
-      minimum-decimal-digits   & Integer & 0     \\
-      round-half               & Choice  & up    \\
-      round-minimum            & Literal & 0     \\
-      round-mode               & Choice  & none  \\
-      round-pad                & Switch  & true  \\
-      round-precision          & Integer & 2     \\
-      round-zero-positive      & Switch  & true  \\
+      drop-exponent               & Switch  & false   \\
+      drop-uncertainty            & Switch  & false   \\
+      drop-zero-decimal           & Switch  & false   \\
+      exponent-mode               & Switch  & input   \\
+      exponent-thresholds         & Literal & -3:3    \\
+      fixed-exponent              & Integer & 0       \\
+      minimum-integer-digits      & Integer & 0       \\
+      minimum-decimal-digits      & Integer & 0       \\
+      round-direction             & Choice  & nearest \\
+      round-half                  & Choice  & up      \\
+      round-minimum               & Literal & 0       \\
+      round-mode                  & Choice  & none    \\
+      round-pad                   & Switch  & true    \\
+      round-precision             & Integer & 2       \\
+      round-zero-positive         & Switch  & true    \\
+      uncertainty-round-direction & Choice  & nearest \\
     \bottomrule
   \end{tabular}
 \end{table}
@@ -1593,12 +1622,32 @@
   \num[round-pad = false]{12.3}
 \end{LaTeXdemo}
 
+\DescribeOption{round-direction}
 \DescribeOption{round-half}
-In cases where the rounded part of a number is exactly half, there are two
-common methods for \enquote{breaking the tie}. The choice of method is
-determined by the option \opt{round-half}, which recognises the choices
-\opt{up} and \opt{even}.
+The detail of which approach to use for rounding may be adjusted using the
+options \opt{round-direction} and \opt{round-half}. The option
+\opt{round-direction} determines which direction a value is rounded toward: a
+choice of \opt{nearest}, \opt{up} or \opt{down}. The standard setting,
+\opt{nearest}, gives the common outcome that values round depending on whether
+the preceding digit is greater or less than \num{5}. The options \opt{up} and
+\opt{down} mean that values are always rounded in one direction: the \opt{down}
+option may be thought of as \enquote{truncation}.
 \begin{LaTeXdemo}
+  \sisetup{round-mode = places}
+  \num{0.054} \\
+  \num{0.046} \\
+  \sisetup{round-direction = down}%
+  \num{0.054} \\
+  \num{0.046} \\
+  \sisetup{round-direction = up}%
+  \num{0.054} \\
+  \num{0.046}
+\end{LaTeXdemo}
+For rounding to \opt{nearest}, where the rounded part of a number is exactly
+half, there are two common methods for \enquote{breaking the tie}. The choice
+of method is determined by the option \opt{round-half}, which recognises the
+choices \opt{up} and \opt{even}.
+\begin{LaTeXdemo}
   \sisetup{
     round-mode      = figures,
     round-precision = 1,
@@ -1611,6 +1660,17 @@
   \num{0.045}
 \end{LaTeXdemo}
 
+\DescribeOption{uncertainty-round-direction}
+When rounding with uncertainties, the direction to round the uncertainty part
+may be set independently of the main number: this is typically used to round
+the uncertainty strictly upward.
+\begin{LaTeXdemo}
+  \sisetup{round-mode = uncertainty}
+  \num{0.123(41)} \\
+  \sisetup{uncertainty-round-direction = up}%
+  \num{0.123(41)}
+\end{LaTeXdemo}
+
 \DescribeOption{round-minimum}
 There are cases in which rounding will result in the number reaching zero. It
 may be desirable to show such results as below a threshold value. This can be
@@ -1944,20 +2004,30 @@
         \multicolumn{1}{l}{Option name} &
         Type &
         \multicolumn{1}{l}{Default\tnote{*}} \\
-      \midrule
-        list-exponents       & Choice  & individual           \\
-        list-final-separator & Literal & \verb*= \text{and} = \\
-        list-pair-separator  & Literal & \verb*= \text{and} = \\
-        list-separator       & Literal & \verb*=\text{,} =    \\
-        list-units           & Choice  & repeat               \\
-        product-exponents    & Choice  & individual           \\
-        product-mode         & Choice  & symbol               \\
-        product-phrase       & Literal & \verb*= \text{by} =  \\
-        product-symbol       & Literal & \cs{times}           \\
-        product-units        & Choice  & repeat               \\
-        range-exponents      & Choice  & individual           \\
-        range-phrase         & Literal & \verb*= \text{to} =  \\
-        range-units          & Choice  & repeat               \\
+      \midrule % (
+        list-close-bracket         & Literal & )                    \\
+        list-exponents             & Choice  & individual           \\
+        list-final-separator       & Literal & \verb*= \text{and} = \\
+        list-independent-prefix    & Switch  & false                \\
+        list-open-bracket          & Literal & (                    \\ % )
+        list-pair-separator        & Literal & \verb*= \text{and} = \\
+        list-separator             & Literal & \verb*=\text{,} =    \\
+        list-units                 & Choice  & repeat               \\ % (
+        product-close-bracket      & Literal & )                    \\
+        product-exponents          & Choice  & individual           \\
+        product-independent-prefix & Switch  & false                \\
+        product-mode               & Choice  & symbol               \\
+        product-open-bracket       & Literal & (                    \\ % )
+        product-phrase             & Literal & \verb*= \text{by} =  \\
+        product-symbol             & Literal & \cs{times}           \\
+        product-units              & Choice  & repeat               \\ % (
+        range-close-bracket        & Literal & )                    \\
+        range-exponents            & Choice  & individual           \\
+        range-independent-prefix   & Switch  & false                \\
+        range-open-bracket         & Literal & (                    \\ % )
+        range-open-phrase          & Literal & \meta{empty}         \\
+        range-phrase               & Literal & \verb*= \text{to} =  \\
+        range-units                & Choice  & repeat               \\
       \bottomrule
     \end{tabular}
     \footnotesize
@@ -2008,6 +2078,7 @@
   \numproduct[product-phrase = { BY }]{5 x 100 x 2} \\
 \end{LaTeXdemo}
 
+\DescribeOption{range-open-phrase}
 \DescribeOption{range-phrase}
 Ranges of numbers can be given as input. These will have an appropriate word or
 symbol inserted between the two entries: this is stored using the
@@ -2017,6 +2088,12 @@
   \numrange{5}{100} \\
   \numrange[range-phrase = --]{5}{100}
 \end{LaTeXdemo}
+In some languages, an opening phrase is \emph{required}; this is supported
+using the \opt{range-open-phrase} key.
+\begin{LaTeXdemo}
+  \numrange{10}{12} \\
+  \numrange[range-open-phrase = {\text{from} }]{5}{100}
+\end{LaTeXdemo}
 
 \DescribeOption{list-exponents}
 \DescribeOption{product-exponents}
@@ -2078,7 +2155,49 @@
   \qtyproduct[product-units = bracket-power]{2 x 4}{\metre} \\
   \qtyproduct[product-units = power]{2 x 4}{\metre}
 \end{LaTeXdemo}
+\DescribeOption{list-close-bracket}
+\DescribeOption{list-open-bracket}
+\DescribeOption{product-close-bracket}
+\DescribeOption{product-open-bracket}
+\DescribeOption{range-close-bracket}
+\DescribeOption{range-open-bracket}
+The brackets used can be customised using the relevant \texttt{\dots-close-bracket}
+and \texttt{\dots-open-bracket} options.
+\begin{LaTeXdemo}
+  \sisetup{
+    list-units         = bracket ,
+    list-open-bracket  = ( ,
+    list-close-bracket = )
+  }
+  \numlist{5e3;7e3;9e3;1e4} \\
+  \sisetup{
+    product-units         = bracket ,
+    product-open-bracket  = ( ,
+    product-close-bracket = )
+  }
+  \numproduct{5e3 x 7e3 x 9e3 x 1e4} \\
+  \sisetup{
+    range-units         = bracket ,
+    range-open-bracket  = ( ,
+    range-close-bracket = )
+  }
+  \qtyrange{2}{4}{\degreeCelsius}
+\end{LaTeXdemo}
 
+\DescribeOption{list-independent-prefix}
+\DescribeOption{product-independent-prefix}
+\DescribeOption{range-independent-prefix}
+When converting exponents to prefixes, there are two possible approaches to the
+case where units are repeated. They can all be converted to use the same
+(initial) prefix, or they can be processed separately. The
+\texttt{\dots-independent-prefix} options are used to control this outcome.
+\begin{LaTeXdemo}
+  \sisetup{exponent-to-prefix = true}%
+  \qtyrange{1e3}{1e9}{\watt}\\
+  \sisetup{range-independent-prefix = true}%
+  \qtyrange{1e3}{1e9}{\watt}
+\end{LaTeXdemo}
+
 \subsection{Complex numbers}
 
 A small number of options apply specifically to the handling of complex
@@ -2664,19 +2783,20 @@
       Type &
       \multicolumn{1}{l@{}}{Default} \\
     \midrule
-      table-align-comparator    & Switch  & true   \\
-      table-align-exponent      & Switch  & true   \\
-      table-align-text-after    & Switch  & true   \\
-      table-align-text-before   & Switch  & true   \\
-      table-align-uncertainty   & Switch  & true   \\
-      table-alignment           & Meta    & center \\
-      table-alignment-mode      & Choice  & marker \\
-      table-auto-round          & Switch  & false  \\
-      table-column-width        & Length  & 0pt    \\
-      table-fixed-width         & Switch  & false  \\
-      table-format              & Special & 2.2    \\
-      table-number-alignment    & Choice  & center \\
-      table-text-alignment      & Choice  & center \\
+      table-align-comparator    & Switch  & true         \\
+      table-align-exponent      & Switch  & true         \\
+      table-align-text-after    & Switch  & true         \\
+      table-align-text-before   & Switch  & true         \\
+      table-align-uncertainty   & Switch  & true         \\
+      table-alignment           & Meta    & center       \\
+      table-alignment-mode      & Choice  & marker       \\
+      table-auto-round          & Switch  & false        \\
+      table-column-width        & Length  & 0pt          \\
+      table-fixed-width         & Switch  & false        \\
+      table-format              & Special & 2.2          \\
+      table-model-setup         & Literal & \meta{empty} \\
+      table-number-alignment    & Choice  & center       \\
+      table-text-alignment      & Choice  & center       \\
     \bottomrule
   \end{tabular}
 \end{table}
@@ -2794,6 +2914,12 @@
 zero). Setting the \opt{table-format} option also resets
 \opt{table-alignment-mode} to \opt{format}.
 
+\DescribeOption{table-model-setup}
+In some tables (particularly those using bold extended fonts), it may be
+necessary to insert additional information when creating the \enquote{model}.
+This is handled using the \opt{table-model-setup} key. An example of the use of
+this key is given in Section~\ref{sec:hint:heading}.
+
 Space for material before and after the \texttt{S} column can be reserved by
 giving model text as part of the \opt{table-format} key. This is then used to
 provide the necessary gap while maintaining alignment (Table~\ref{tab:S:ends}).
@@ -3122,6 +3248,15 @@
 
 \subsection{Preamble-only options}
 
+\DescribeOption{list-input-separator}
+\DescribeOption{product-input-separator}
+The separator between \emph{input} elements of lists (\cs{numlist},
+\cs{qtylist}) and products (\cs{numproduct}, \cs{qtyproduct}) can be adjusted
+using the options \opt{list-input-separator} and \opt{product-input-separator},
+respectively. These are load-time only options as the separator here is part of
+the \enquote{document interface} rather than part of the individual number(s).
+The supplied value should be a \emph{single} marker.
+
 \DescribeOption{table-column-type}
 The letter(s) used to create table columns can be adjusted using the
 \opt{table-column-type} option. The standard setting is |S|, but one or more
@@ -3753,7 +3888,11 @@
 demonstrated in Section~\ref{sec:hint:expanding}), then to use this macro to
 make the heading cells bold. This approach is illustrated in
 Table~\ref{tab:xmpl:headers}, along with the use of \cs{rowcolor} to provide a
-background color.
+background color. Some typical \LaTeX{} font arrangements use a wider
+(extended) width for the bold font compared with the normal font. This will
+disturb the alignment if the \opt{table-format} is not symmetrical. For these
+cases, the \opt{table-model-setup} key may be used to apply the wider font to
+the \enquote{model} used in ensuring alignment.
 \begin{LaTeXdemo}[code and float]
   \begin{table}
     \caption{Header row in a table.%
@@ -3760,13 +3899,19 @@
       \label{tab:xmpl:headers}}
     \robustify\bfseries
     \centering
+    \sisetup{text-series-to-math}
     \begin{tabular}
-      {@{}S[text-series-to-math, table-format = 3.3]@{}}
+      {
+        @{}
+        S[table-format = 3.3]
+        S[table-format = 3.6, table-model-setup = \bfseries]
+        @{}
+      }
       \rowcolor[gray]{0.9}
-      \bfseries 123.456 \\
-       23.45  \\
-      123.4   \\
-        3.456 \\
+      \bfseries 123.456 & \bfseries 123.456789 \\
+       23.45  &  23.45  \\
+      123.4   & 123.4   \\
+        3.456 &   3.456 \\
     \end{tabular}
   \end{table}
 \end{LaTeXdemo}
@@ -3852,6 +3997,63 @@
   \input{siunitx-local-units}
 \end{LaTeXdemo}
 
+\subsection{Overloading the standard interfaces%
+  \label{sec:hint:overload}}
+
+The interfaces in \pkg{siunitx} deliberately split up different types of
+numerical input (ranges, products, etc.) for semantic reasons. This also means
+that there is less chance of confusion in parsing input. However, some users
+would prefer to overload the \cs{num} and \cs{qty} commands such that they
+accept multiple different types of input. There is a code-level interface that
+could be used for this, but most end-users will likely want to avoid this. A
+possible approach that covers most of the common cases is.
+\begin{LaTeXdemo}[code only]
+  \ExplSyntaxOn
+  \cs_gset_eq:NN \ifstrpresent \tl_if_in:nnTF
+  \ExplSyntaxOff
+  \NewCommandCopy\oldnum\num
+  \NewCommandCopy\oldnumrange\numrange
+  \RenewDocumentCommand\num{O{}m}{%
+    \ifstrpresent{#2}{x}
+      {\numproduct[#1]{#2}}
+      {%
+        \ifstrpresent{#2}{;}
+          {\numlist[#1]{#2}}
+          {%
+            \ifstrpresent{#2}{:}
+              {\numrange[#1]{#2}}
+              {\oldnum[#1]{#2}}%
+          }%
+      }%
+  }
+  \RenewDocumentCommand\numrange{O{}>{\SplitList{:}}m}
+    {\oldnumrange[#1]#2}
+\end{LaTeXdemo}
+for the \cs{num} command and
+\begin{LaTeXdemo}[code only]
+  \ExplSyntaxOn
+  \cs_gset_eq:NN \ifstrpresent \tl_if_in:nnTF
+  \ExplSyntaxOff
+  \NewCommandCopy\oldqty\qty
+  \NewCommandCopy\oldqtyrange\qtyrange
+  \RenewDocumentCommand\qty{O{}mm}{%
+    \ifstrpresent{#2}{x}
+     {\qtyproduct[#1]{#2}{#3}}
+     {%
+       \ifstrpresent{#2}{;}
+          {\qtylist[#1]{#2}{#3}}
+          {%
+            \ifstrpresent{#2}{:}
+              {\qtyrange[#1]{#2}{#3}}
+              {\oldqty[#1]{#2}{#3}}%
+          }%
+      }%
+  }
+  \RenewDocumentCommand\qtyrange{O{}>{\SplitList{:}}mm}
+    {\oldqtyrange[#1]#2{#3}}
+\end{LaTeXdemo}
+for \cs{qty}.
+
 \section{Using (\acro{SI}) units}
 
 Consistent and logical units are a necessity for scientific work, and have

Modified: trunk/Master/texmf-dist/tex/latex/siunitx/siunitx.sty
===================================================================
--- trunk/Master/texmf-dist/tex/latex/siunitx/siunitx.sty	2023-07-31 20:11:33 UTC (rev 67779)
+++ trunk/Master/texmf-dist/tex/latex/siunitx/siunitx.sty	2023-07-31 20:18:52 UTC (rev 67780)
@@ -5,11 +5,11 @@
 %% The original source files were:
 %%
 %% siunitx.dtx  (with options: `package,init')
+%% siunitx-number.dtx  (with options: `package')
 %% siunitx-angle.dtx  (with options: `package')
 %% siunitx-complex.dtx  (with options: `package')
 %% siunitx-compound.dtx  (with options: `package')
 %% siunitx-locale.dtx  (with options: `package')
-%% siunitx-number.dtx  (with options: `package')
 %% siunitx-print.dtx  (with options: `package')
 %% siunitx-table.dtx  (with options: `package')
 %% siunitx-unit.dtx  (with options: `package')
@@ -42,7 +42,7 @@
       }%
     \endinput
   }%
-\ProvidesExplPackage {siunitx} {2023-07-26} {3.2.9}
+\ProvidesExplPackage {siunitx} {2023-07-31} {3.3.0}
   {A comprehensive (SI) units package}
 \msg_new:nnnn { siunitx } { incompatible-package }
   { Package~'#1'~incompatible. }
@@ -63,1733 +63,6 @@
   }
 \providecommand \IfFormatAtLeastTF { \@ifl at t@r \fmtversion }
 \tl_new:N \l__siunitx_tmp_tl
-\bool_new:N \l__siunitx_angle_tmp_bool
-\dim_new:N \l__siunitx_angle_tmp_dim
-\tl_new:N \l__siunitx_angle_tmp_tl
-\keys_define:nn { siunitx }
-  {
-    angle-mode .choice: ,
-    angle-mode / arc .code:n =
-      {
-        \bool_set_true:N \l__siunitx_angle_force_arc_bool
-        \bool_set_false:N \l__siunitx_angle_force_decimal_bool
-      } ,
-    angle-mode / decimal .code:n =
-      {
-        \bool_set_false:N \l__siunitx_angle_force_arc_bool
-        \bool_set_true:N \l__siunitx_angle_force_decimal_bool
-      } ,
-    angle-mode / input .code:n =
-      {
-        \bool_set_false:N \l__siunitx_angle_force_arc_bool
-        \bool_set_false:N \l__siunitx_angle_force_decimal_bool
-      } ,
-    angle-symbol-degree .tl_set:N =
-      \l__siunitx_angle_symbol_degree_tl ,
-    angle-symbol-minute .tl_set:N =
-      \l__siunitx_angle_symbol_minute_tl ,
-    angle-symbol-second .tl_set:N =
-      \l__siunitx_angle_symbol_second_tl ,
-    angle-symbol-over-decimal .bool_set:N =
-      \l__siunitx_angle_astronomy_bool ,
-    angle-separator .tl_set:N =
-      \l__siunitx_angle_separator_tl ,
-    fill-angle-degrees .bool_set:N =
-      \l__siunitx_angle_fill_degrees_bool ,
-    fill-angle-minutes .bool_set:N =
-      \l__siunitx_angle_fill_minutes_bool ,
-    fill-angle-seconds .bool_set:N =
-      \l__siunitx_angle_fill_seconds_bool ,
-    number-angle-product .tl_set:N =
-      \l__siunitx_angle_product_tl
-  }
-\bool_new:N \l__siunitx_angle_force_arc_bool
-\bool_new:N \l__siunitx_angle_force_decimal_bool
-\cs_new_protected:Npn \siunitx_angle:n #1
-  {
-    \bool_if:NTF \l_siunitx_number_parse_bool
-      { \__siunitx_angle_angle:n {#1} }
-      {
-        \tl_if_blank:nF {#1}
-          {
-            \tl_set:Nn \l__siunitx_angle_degrees_tl { \ensuremath {#1} }
-            \__siunitx_angle_arc_print:VVV
-              \l__siunitx_angle_degrees_tl
-              \c_empty_tl
-              \c_empty_tl
-          }
-      }
-  }
-\cs_new_protected:Npn \__siunitx_angle_angle:n #1
-  {
-    \bool_if:NTF \l__siunitx_angle_force_arc_bool
-      { \exp_args:Ne \__siunitx_angle_arc_convert:n { \fp_eval:n {#1} } }
-      {
-        \siunitx_number_parse:nN {#1} \l__siunitx_angle_degrees_tl
-        \siunitx_number_process:NN \l__siunitx_angle_degrees_tl \l__siunitx_angle_degrees_tl
-        \tl_set:Nx \l__siunitx_angle_degrees_tl
-          { \siunitx_number_output:NN \l__siunitx_angle_degrees_tl \q_nil }
-        \__siunitx_angle_arc_print:VVV
-          \l__siunitx_angle_degrees_tl
-          \c_empty_tl
-          \c_empty_tl
-      }
-  }
-\cs_new_protected:Npn \siunitx_angle:nnn #1#2#3
-  {
-    \bool_if:NTF \l_siunitx_number_parse_bool
-      {
-        \bool_if:NTF \l__siunitx_angle_force_decimal_bool
-          {
-            \exp_args:Ne \siunitx_angle:n
-              { \fp_eval:n { #1 + (#2) / 60 + (#3) / 3600 } }
-          }
-          { \__siunitx_angle_arc_sign:nnn {#1} {#2} {#3} }
-      }
-      {
-        \tl_set:Nx \l__siunitx_angle_degrees_tl
-          { \tl_if_blank:nF {#1} { \exp_not:n { \ensuremath {#1} } } }
-        \tl_set:Nx \l__siunitx_angle_minutes_tl
-          { \tl_if_blank:nF {#2} { \exp_not:n { \ensuremath {#2} } } }
-        \tl_set:Nx \l__siunitx_angle_seconds_tl
-          { \tl_if_blank:nF {#3} { \exp_not:n { \ensuremath {#3} } } }
-        \__siunitx_angle_arc_print:VVV
-          \l__siunitx_angle_degrees_tl
-          \l__siunitx_angle_minutes_tl
-          \l__siunitx_angle_seconds_tl
-      }
-  }
-\cs_new_protected:Npn \__siunitx_angle_arc_convert:n #1
-  {
-    \use:x
-      {
-        \siunitx_angle:nnn
-          { \fp_eval:n { trunc(#1,0) } }
-          { \fp_eval:n { trunc((#1 - trunc(#1,0)) * 60,0) } }
-          {
-            \fp_eval:n
-              {
-                (
-                          (#1 - trunc(#1,0)) * 60
-                  - trunc((#1 - trunc(#1,0)) * 60,0)
-                )
-                * 60
-              }
-          }
-      }
-  }
-\tl_new:N \l__siunitx_angle_degrees_tl
-\tl_new:N \l__siunitx_angle_minutes_tl
-\tl_new:N \l__siunitx_angle_seconds_tl
-\tl_new:N \l__siunitx_angle_sign_tl
-\cs_new_protected:Npn \__siunitx_angle_arc_sign:nnn #1#2#3
-  {
-    \group_begin:
-      \keys_set:nn { siunitx }
-        {
-          input-close-uncertainty = ,
-          input-exponent-markers  = ,
-          input-open-uncertainty  = ,
-          input-uncertainty-signs =
-        }
-      \tl_clear:N \l__siunitx_angle_sign_tl
-      \__siunitx_angle_arc_sign:nn {#1} { degrees }
-      \__siunitx_angle_arc_sign:nn {#2} { minutes }
-      \__siunitx_angle_arc_sign:nn {#3} { seconds }
-      \tl_if_empty:NF \l__siunitx_angle_sign_tl
-        {
-          \clist_map_inline:nn { degrees , minutes , seconds }
-            {
-              \tl_if_empty:cF { l__siunitx_angle_ ##1 _tl }
-                {
-                  \tl_set:cx { l__siunitx_angle_ ##1 _tl }
-                    {
-                       { }
-                       { \exp_not:V \l__siunitx_angle_sign_tl }
-                       \exp_after:wN \exp_after:wN \exp_after:wN
-                         \__siunitx_angle_sign:nnnnnnn
-                           \cs:w l__siunitx_angle_ ##1 _tl \cs_end:
-                    }
-                  \clist_map_break:
-                }
-            }
-        }
-      \clist_map_inline:nn { degrees , minutes , seconds }
-        {
-          \tl_if_empty:cF { l__siunitx_angle_ ##1 _tl }
-            {
-              \exp_args:Ncc \siunitx_number_process:NN
-                { l__siunitx_angle_ ##1 _tl } { l__siunitx_angle_ ##1 _tl }
-              \tl_set:cx { l__siunitx_angle_ ##1 _tl }
-                {
-                  \exp_args:Nc \siunitx_number_output:NN
-                    { l__siunitx_angle_ ##1 _tl } \q_nil
-                }
-            }
-        }
-      \__siunitx_angle_arc_print:VVV
-        \l__siunitx_angle_degrees_tl
-        \l__siunitx_angle_minutes_tl
-        \l__siunitx_angle_seconds_tl
-    \group_end:
-  }
-\cs_new_protected:Npn \__siunitx_angle_arc_sign:nn #1#2
-  {
-    \tl_if_blank:nTF {#1}
-      {
-        \bool_if:cTF { l__siunitx_angle_fill_ #2 _bool }
-          {
-            \tl_set:cn { l__siunitx_angle_ #2 _tl }
-              { { } { } { 0 } { } { } { } { 0 } }
-          }
-          { \tl_clear:c { l__siunitx_angle_ #2 _tl } }
-      }
-      {
-        \siunitx_number_parse:nN {#1} \l__siunitx_angle_tmp_tl
-        \exp_after:wN \__siunitx_angle_extract_sign:nnnnnnnn \l__siunitx_angle_tmp_tl {#2}
-      }
-  }
-\cs_new_protected:Npn \__siunitx_angle_extract_sign:nnnnnnnn #1#2#3#4#5#6#7#8
-  {
-    \tl_if_blank:nTF {#2}
-      { \tl_set_eq:cN { l__siunitx_angle_ #8 _tl } \l__siunitx_angle_tmp_tl }
-      {
-        \tl_set:cn { l__siunitx_angle_ #8 _tl }
-          { {#1} { } {#3} {#4} {#5} {#6} {#7} }
-        \tl_set:Nn \l__siunitx_angle_sign_tl {#2}
-        \keys_set:nn { siunitx }
-          { input-comparators = , input-signs = }
-      }
-  }
-\cs_new:Npn \__siunitx_angle_sign:nnnnnnn #1#2#3#4#5#6#7
-  { \exp_not:n { {#3} {#4} {#5} {#6} {#7} } }
-\box_new:N \l__siunitx_angle_marker_box
-\box_new:N \l__siunitx_angle_unit_box
-\cs_new_protected:Npn \__siunitx_angle_arc_print:nnn #1#2#3
-  {
-    \__siunitx_angle_arc_print_auxi:nVn {#1}
-      \l__siunitx_angle_symbol_degree_tl {#2#3}
-    \__siunitx_angle_arc_print_auxi:nVn {#2}
-      \l__siunitx_angle_symbol_minute_tl {#3}
-    \__siunitx_angle_arc_print_auxi:nVn {#3}
-      \l__siunitx_angle_symbol_second_tl { }
-  }
-\cs_generate_variant:Nn \__siunitx_angle_arc_print:nnn { VVV }
-\cs_new_protected:Npn \__siunitx_angle_arc_print_auxi:nnn #1#2#3
-  {
-    \tl_if_blank:nF {#1}
-      {
-        \bool_if:NTF \l_siunitx_number_parse_bool
-          {
-            \bool_if:NTF \l__siunitx_angle_astronomy_bool
-              { \__siunitx_angle_arc_print_auxii:nw {#2} #1 \q_stop }
-              {
-                \__siunitx_angle_arc_print_auxv:w #1 \q_stop
-                \__siunitx_angle_arc_print_auxvi:n {#2}
-              }
-          }
-          {
-            \siunitx_print_number:n {#1}
-            \__siunitx_angle_arc_print_auxvi:n {#2}
-          }
-       \tl_if_blank:nF {#3}
-          {
-            \nobreak
-            \l__siunitx_angle_separator_tl
-          }
-      }
-  }
-\cs_generate_variant:Nn \__siunitx_angle_arc_print_auxi:nnn { nV }
-\cs_new_protected:Npn \__siunitx_angle_arc_print_auxii:nw
-  #1#2 \q_nil #3 \q_nil #4 \q_nil #5 \q_nil #6 \q_nil #7 \q_nil #8 \q_stop
-  {
-    \mode_if_math:TF
-      { \bool_set_true:N \l__siunitx_angle_tmp_bool }
-      { \bool_set_false:N \l__siunitx_angle_tmp_bool }
-    \siunitx_print_number:n {#2#3#4}
-    \tl_if_blank:nTF {#6}
-      { \__siunitx_angle_arc_print_auxvi:n {#1} }
-      {
-        \hbox_set:Nn \l__siunitx_angle_marker_box
-          {
-            \__siunitx_angle_arc_print_auxiii:n
-               { \siunitx_print_number:n {#5} }
-          }
-        \hbox_set:Nn \l__siunitx_angle_unit_box
-          {
-            \__siunitx_angle_arc_print_auxiii:n
-              {
-                \siunitx_unit_format:nN {#1} \l__siunitx_angle_tmp_tl
-                \siunitx_print_unit:V \l__siunitx_angle_tmp_tl
-                \skip_horizontal:n { -\scriptspace }
-              }
-          }
-        \dim_compare:nNnTF { \box_wd:N \l__siunitx_angle_marker_box } >
-          { \box_wd:N \l__siunitx_angle_unit_box }
-          {
-            \__siunitx_angle_arc_print_auxiv:NN
-              \l__siunitx_angle_marker_box
-              \l__siunitx_angle_unit_box
-          }
-          {
-            \__siunitx_angle_arc_print_auxiv:NN
-              \l__siunitx_angle_unit_box
-              \l__siunitx_angle_marker_box
-          }
-        \hbox_set_to_wd:Nnn \l__siunitx_angle_marker_box
-          \l__siunitx_angle_tmp_dim
-          {
-            \hbox_overlap_right:n
-              { \box_use_drop:N \l__siunitx_angle_marker_box }
-            \hbox_overlap_right:n
-              { \box_use_drop:N \l__siunitx_angle_unit_box }
-            \tex_hfil:D
-          }
-        \box_use:N \l__siunitx_angle_marker_box
-        \skip_horizontal:N \scriptspace
-        \siunitx_print_number:n {#6}
-      }
-  }
-\cs_new_protected:Npn \__siunitx_angle_arc_print_auxiii:n #1
-  {
-    \bool_if:NTF \l__siunitx_angle_tmp_bool
-      { \ensuremath }
-      { \use:n }
-        {#1}
-  }
-\cs_new_protected:Npn \__siunitx_angle_arc_print_auxiv:NN #1#2
-  {
-    \dim_set:Nn \l__siunitx_angle_tmp_dim { \box_wd:N #1 }
-    \hbox_set_to_wd:Nnn #2
-      \l__siunitx_angle_tmp_dim
-      {
-        \tex_hss:D
-        \hbox_unpack_drop:N #2
-        \tex_hss:D
-      }
-  }
-\cs_new_protected:Npn \__siunitx_angle_arc_print_auxv:w
-  #1 \q_nil #2 \q_nil #3 \q_nil #4 \q_nil #5 \q_nil #6 \q_stop
-  { \siunitx_print_number:n {#1#2#3#4#5} }
-\cs_new_protected:Npn \__siunitx_angle_arc_print_auxvi:n #1
-  {
-    \nobreak
-    \l__siunitx_angle_product_tl
-    \siunitx_unit_format:nN {#1} \l__siunitx_angle_tmp_tl
-    \siunitx_print_unit:V \l__siunitx_angle_tmp_tl
-  }
-\keys_set:nn { siunitx }
-  {
-    angle-mode                = input      ,
-    angle-symbol-degree       = \degree    ,
-    angle-symbol-minute       = \arcminute ,
-    angle-symbol-over-decimal = false      ,
-    angle-symbol-second       = \arcsecond ,
-    angle-separator           =            ,
-    fill-angle-degrees        = false      ,
-    fill-angle-minutes        = false      ,
-    fill-angle-seconds        = false      ,
-    number-angle-product      =
-  }
-\fp_new:N \l__siunitx_complex_tmp_fp
-\tl_new:N \l__siunitx_complex_tmp_tl
-\tl_new:N \l__siunitx_complex_input_tl
-\tl_new:N \l__siunitx_complex_comparator_tl
-\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 =
-      \l__siunitx_complex_output_root_tl ,
-    print-complex-unity .bool_set:N =
-      \l__siunitx_complex_print_unity_bool
-  }
-\cs_new_protected:Npn \__siunitx_complex_parse:nNN #1#2#3
-  {
-    \group_begin:
-      \__siunitx_complex_parse_clear:
-      \protected at edef \l__siunitx_complex_arg_tl {#1}
-      \tl_set_eq:NN \l__siunitx_complex_input_tl \l__siunitx_complex_arg_tl
-      \siunitx_number_normalize_symbols:N \l__siunitx_complex_arg_tl
-      \tl_if_empty:NF \l__siunitx_complex_arg_tl
-        { \__siunitx_complex_parse_comparator: }
-      \__siunitx_complex_parse_check:
-      \cs_set_protected:Npx \__siunitx_complex_parse_end:
-        {
-          \tl_set:Nn \exp_not:N #2 { \exp_not:V \l__siunitx_complex_real_tl }
-          \tl_set:Nn \exp_not:N #3 { \exp_not:V \l__siunitx_complex_img_tl }
-        }
-    \exp_after:wN \group_end:
-    \__siunitx_complex_parse_end:
-  }
-\cs_new_protected:Npn \__siunitx_complex_parse_end: { }
-\cs_new_protected:Npn \__siunitx_complex_parse_clear:
-  {
-    \tl_clear:N \l__siunitx_complex_real_tl
-    \tl_clear:N \l__siunitx_complex_img_tl
-    \tl_clear:N \l__siunitx_complex_exp_tl
-    \tl_clear:N \l__siunitx_complex_sign_tl
-    \tl_clear:N \l__siunitx_complex_join_tl
-  }
-\cs_new_protected:Npn \__siunitx_complex_parse_check:
-  {
-    \tl_if_empty:NTF \l__siunitx_complex_img_tl
-      { \__siunitx_complex_parse_check:N \l__siunitx_complex_real_tl }
-      {
-        \tl_if_empty:NTF \l__siunitx_complex_real_tl
-          { \__siunitx_complex_parse_check:N \l__siunitx_complex_img_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_check:N \l__siunitx_complex_img_tl
-          }
-      }
-  }
-\cs_new_protected:Npn \__siunitx_complex_parse_check:N #1
-  {
-    \tl_set:Nx #1
-      {
-        \exp_not:V \l__siunitx_complex_comparator_tl
-        \exp_not:V \l__siunitx_complex_sign_tl
-        \exp_not:V #1
-        \exp_not:V \l__siunitx_complex_exp_tl
-      }
-    \tl_clear:N \l__siunitx_complex_comparator_tl
-    \tl_clear:N \l__siunitx_complex_sign_tl
-    \siunitx_number_parse:VN #1 #1
-  }
-\cs_new_protected:Npn \__siunitx_complex_parse_comparator:
-  {
-    \exp_after:wN \__siunitx_complex_parse_comparator_aux:Nw
-      \l__siunitx_complex_arg_tl \q_stop
-  }
-\cs_new_protected:Npn \__siunitx_complex_parse_comparator_aux:Nw #1#2 \q_stop
-  {
-    \tl_if_in:NnTF \l_siunitx_number_input_comparator_tl {#1}
-      {
-        \tl_set:Nn \l__siunitx_complex_comparator_tl {#1}
-        \tl_set:Nn \l__siunitx_complex_arg_tl {#2}
-      }
-      { \tl_clear:N \l__siunitx_complex_comparator_tl }
-    \tl_if_empty:NF \l__siunitx_complex_arg_tl
-      { \__siunitx_complex_parse_sign: }
-  }
-\cs_new_protected:Npn \__siunitx_complex_parse_exponent:
-  {
-    \tl_if_empty:NTF \l_siunitx_number_input_exponent_tl
-      { \__siunitx_complex_parse_root: }
-      {
-        \tl_set:Nx \l__siunitx_complex_tmp_tl
-          { \tl_head:V \l_siunitx_number_input_exponent_tl }
-        \tl_map_inline:Nn \l_siunitx_number_input_exponent_tl
-          {
-            \tl_replace_all:NnV \l__siunitx_complex_arg_tl
-              {##1} \l__siunitx_complex_tmp_tl
-          }
-        \use:x
-          {
-            \cs_set_protected:Npn
-              \exp_not:N \__siunitx_complex_parse_exponent_auxi:w
-              ####1 \exp_not:V \l__siunitx_complex_tmp_tl
-              ####2 \exp_not:V \l__siunitx_complex_tmp_tl
-              ####3 \exp_not:N \q_stop
-          }
-            { \__siunitx_complex_parse_exponent_auxii:nn {##1} {##2} }
-        \use:x
-          {
-            \__siunitx_complex_parse_exponent_auxi:w
-              \exp_not:V \l__siunitx_complex_arg_tl
-              \exp_not:V \l__siunitx_complex_tmp_tl \exp_not:N \q_nil
-              \exp_not:V \l__siunitx_complex_tmp_tl \exp_not:N \q_stop
-          }
-      }
-  }
-\cs_new_protected:Npn \__siunitx_complex_parse_exponent_auxi:w  { }
-\cs_new_protected:Npn \__siunitx_complex_parse_exponent_auxii:nn #1#2
-  {
-    \quark_if_nil:nF {#2}
-      {
-        \tl_set:Nn \l__siunitx_complex_arg_tl {#1}
-        \tl_set:Nx \l__siunitx_complex_exp_tl
-          { \exp_not:V \l__siunitx_complex_tmp_tl \exp_not:n {#2} }
-      }
-    \__siunitx_complex_parse_root:
-  }
-\cs_new_protected:Npn \__siunitx_complex_parse_root:
-  {
-    \tl_if_empty:NTF \l__siunitx_complex_input_root_tl
-      { \tl_set_eq:NN \l__siunitx_complex_real_tl \l__siunitx_complex_arg_tl }
-      {
-        \tl_set:Nx \l__siunitx_complex_tmp_tl
-          { \tl_head:V \l__siunitx_complex_input_root_tl }
-        \tl_map_inline:Nn \l__siunitx_complex_input_root_tl
-          {
-            \tl_replace_all:NnV \l__siunitx_complex_arg_tl
-              {##1} \l__siunitx_complex_tmp_tl
-          }
-        \use:x
-          {
-            \cs_set_protected:Npn
-              \exp_not:N \__siunitx_complex_parse_root_auxi:w
-              ####1 \exp_not:V \l__siunitx_complex_tmp_tl
-              ####2 \exp_not:V \l__siunitx_complex_tmp_tl
-              ####3 \exp_not:N \q_stop
-          }
-            { \__siunitx_complex_parse_root_auxii:nn {##1} {##2} }
-        \use:x
-          {
-            \__siunitx_complex_parse_root_auxi:w
-              \exp_not:V \l__siunitx_complex_arg_tl
-              \exp_not:V \l__siunitx_complex_tmp_tl \exp_not:N \q_nil
-              \exp_not:V \l__siunitx_complex_tmp_tl \exp_not:N \q_stop
-          }
-      }
-  }
-\cs_new_protected:Npn \__siunitx_complex_parse_root_auxi:w  { }
-\cs_new_protected:Npn \__siunitx_complex_parse_root_auxii:nn #1#2
-  {
-    \quark_if_nil:nTF {#2}
-      { \tl_set:Nn \l__siunitx_complex_real_tl {#1} }
-      {
-        \tl_set:Nn \l__siunitx_complex_img_tl {#2}
-        \tl_if_blank:nTF {#1}
-          {
-            \tl_if_blank:nT {#2}
-              { \tl_set:Nn \l__siunitx_complex_img_tl { 1 } }
-          }
-          {
-            \tl_if_blank:nTF {#2}
-              { \__siunitx_complex_parse_split:n {#1} }
-              { \__siunitx_complex_parse_sign_check:n {#1} }
-          }
-      }
-  }
-\cs_new_protected:Npn \__siunitx_complex_parse_sign:
-  {
-    \exp_after:wN \__siunitx_complex_parse_sign_aux:Nw
-      \l__siunitx_complex_arg_tl \q_stop
-  }
-\cs_new_protected:Npn \__siunitx_complex_parse_sign_aux:Nw #1#2 \q_stop
-  {
-    \tl_if_in:NnT \l_siunitx_number_input_sign_tl {#1}
-      {
-        \tl_set:Nn \l__siunitx_complex_sign_tl {#1}
-        \tl_set:Nn \l__siunitx_complex_arg_tl {#2}
-      }
-    \tl_if_empty:NF \l__siunitx_complex_arg_tl
-      { \__siunitx_complex_parse_exponent: }
-  }
-\cs_new_protected:Npn \__siunitx_complex_parse_sign_check:n #1
-  {
-    \__siunitx_complex_parse_sign_check:nN { } #1 \q_recursion_tail \q_recursion_stop
-  }
-\cs_new_protected:Npn \__siunitx_complex_parse_sign_check:nN #1#2
-  {
-    \quark_if_recursion_tail_stop_do:Nn #2
-      { \__siunitx_complex_parse_clear: }
-    \tl_if_in:NnTF \l_siunitx_number_input_sign_tl {#2}
-      { \__siunitx_complex_parse_sign_check:nNw {#1} #2 }
-      { \__siunitx_complex_parse_sign_check:nN {#1#2} }
-  }
-\cs_new_protected:Npn \__siunitx_complex_parse_sign_check:nNw
-  #1#2 #3 \q_recursion_tail \q_recursion_stop
-  {
-    \tl_if_blank:nTF {#3}
-      {
-        \tl_if_blank:nTF {#1}
-          { \__siunitx_complex_parse_clear: }
-          {
-            \tl_set:Nn \l__siunitx_complex_real_tl {#1}
-            \tl_set:Nn \l__siunitx_complex_join_tl {#2}
-          }
-      }
-      { \__siunitx_complex_parse_clear: }
-  }
-\cs_new_protected:Npn \__siunitx_complex_parse_split:n #1
-  {
-    \__siunitx_complex_parse_split:nN { } #1 \q_recursion_tail \q_recursion_stop
-  }
-\cs_new_protected:Npn \__siunitx_complex_parse_split:nN #1#2
-  {
-    \quark_if_recursion_tail_stop_do:Nn #2
-      { \tl_set:Nn \l__siunitx_complex_img_tl {#1} }
-    \tl_if_in:NnTF \l_siunitx_number_input_sign_tl {#2}
-      {
-        \tl_set:Nn \l__siunitx_complex_real_tl {#1}
-        \tl_set:Nn \l__siunitx_complex_join_tl {#2}
-        \__siunitx_complex_parse_split:w
-      }
-      { \__siunitx_complex_parse_split:nN {#1#2} }
-  }
-\cs_new_protected:Npn \__siunitx_complex_parse_split:w #1 \q_recursion_tail \q_recursion_stop
-  {
-    \tl_set:Nx \l__siunitx_complex_img_tl
-      {
-        \tl_if_blank:nTF {#1}
-          { 1 }
-          { \exp_not:n {#1} }
-     }
-    \tl_if_empty:NT \l__siunitx_complex_real_tl
-      { \__siunitx_complex_parse_clear: }
-  }
-\cs_new_protected:Npn \__siunitx_complex_parse_polar:nn #1#2
-  {
-    \bool_if:NTF \l_siunitx_number_parse_bool
-      { \siunitx_number_parse:nN {#1} \l__siunitx_complex_mag_tl }
-      { \tl_set:Nn \l__siunitx_complex_mag_tl { \ensuremath {#1} } }
-    \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 { ( }
-\tl_set:Nn \l__siunitx_complex_bracket_close_tl { ) }
-\tl_new:N \l__siunitx_complex_unit_tl
-\cs_new_protected:Npn \siunitx_complex_number:n #1
-  {
-    \bool_lazy_and:nnTF
-      { \l__siunitx_complex_force_polar_bool }
-      { \l_siunitx_number_parse_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_lazy_and:nnTF
-      { \l__siunitx_complex_force_cartesian_bool }
-      { \l_siunitx_number_parse_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
-  {
-    \bool_lazy_and:nnTF
-      { \l__siunitx_complex_force_polar_bool }
-      { \l_siunitx_number_parse_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_lazy_and:nnTF
-      { \l__siunitx_complex_force_cartesian_bool }
-      { \l_siunitx_number_parse_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_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_cartesian_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
-      {
-        \siunitx_number_process:NN \l__siunitx_complex_real_tl \l__siunitx_complex_real_tl
-        \tl_set:Nx \l__siunitx_complex_tmp_tl
-          { \siunitx_number_output:N \l__siunitx_complex_real_tl }
-      }
-      { \__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_cartesian_auxii: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
-    \tl_set:Nx \l__siunitx_complex_tmp_tl
-      { \siunitx_number_output:NN \l__siunitx_complex_img_tl \q_nil }
-    \exp_after:wN \__siunitx_complex_extract_exponent:w \l__siunitx_complex_tmp_tl \q_stop
-    \tl_set:Nx \l__siunitx_complex_tmp_tl
-      {
-        \bool_lazy_or:nnTF
-          {
-            \bool_lazy_and_p:nn
-              { \l_siunitx_number_bracket_ambiguous_bool }
-              { ! \tl_if_empty_p:N \l__siunitx_complex_exp_tl }
-          }
-          {
-            ! \bool_lazy_any_p:n
-              {
-                { \tl_if_blank_p:n {#1} }
-                { \tl_if_empty_p:N \l__siunitx_complex_real_tl }
-                { \tl_if_empty_p:N \l__siunitx_complex_img_tl }
-              }
-          }
-          { \__siunitx_complex_format_bracket:n }
-          { \use:n }
-          {
-            \siunitx_number_output:N \l__siunitx_complex_real_tl
-            \exp_not:V \l__siunitx_complex_sign_tl
-            \bool_if:NF \l__siunitx_complex_root_after_bool
-              { \exp_not:V \l__siunitx_complex_output_root_tl }
-             \exp_not:V \l__siunitx_complex_tmp_tl
-            \bool_if:NT \l__siunitx_complex_root_after_bool
-              { \exp_not:V \l__siunitx_complex_output_root_tl }
-           }
-         \exp_not:V \l__siunitx_complex_exp_tl
-      }
-  }
-\cs_new_protected:Npn \__siunitx_complex_drop_exponent:nnnnnnn #1#2#3#4#5#6#7
-  { \tl_set:Nn \l__siunitx_complex_real_tl { {#1} {#2} {#3} {#4} {#5} { } { 0 } } }
-\cs_new_protected:Npn \__siunitx_complex_format_sign:nnnnnnn #1#2#3#4#5#6#7
-  {
-    \tl_set:Nx \l__siunitx_complex_img_tl
-      {
-        { }
-        {
-          \tl_if_blank:nTF {#2}
-            { \tl_if_empty:NF \l__siunitx_complex_real_tl { + } }
-            { \exp_not:n {#2} }
-        }
-        \exp_not:n { {#3} {#4} {#5} {#6} {#7} }
-      }
-  }
-\cs_new_protected:Npn \__siunitx_complex_extract_exponent:w
-  #1 \q_nil #2 \q_nil #3 \q_nil #4 \q_nil #5 \q_nil #6 \q_nil #7 \q_nil #8
-  \q_nil #9 \q_stop
-  {
-    \tl_set:Nn \l__siunitx_complex_sign_tl {#1#2}
-    \bool_lazy_all:nTF
-      {
-        { ! \l__siunitx_complex_print_unity_bool }
-        { \str_if_eq_p:nn {#3} { 1 } }
-        { \tl_if_blank_p:n {#5} }
-      }
-      { \__siunitx_complex_extract_exponent_aux:nw {#6#7#8} }
-      { \__siunitx_complex_extract_exponent_aux:nw {#3#4#5#6#7#8} }
-         #9 \q_stop
-  }
-\cs_new:Npn \__siunitx_complex_extract_exponent_aux:nw
-  #1#2 \q_nil #3 \q_nil #4 \q_stop
-  {
-    \tl_set:Nn \l__siunitx_complex_tmp_tl {#1#2}
-    \tl_set:Nn \l__siunitx_complex_exp_tl {#3#4}
-  }
-\cs_new_protected:Npn \__siunitx_complex_format_bracket:n #1
-  {
-    \exp_not:V \l__siunitx_complex_bracket_open_tl
-    #1
-    \exp_not:V \l__siunitx_complex_bracket_close_tl
-  }
-\cs_new_protected:Npn \__siunitx_complex_format_cartesian_units:n #1
-  {
-    \tl_if_blank:nTF {#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
-      }
-      {
-        \use:c
-          { __siunitx_complex_format_cartesian_ \l_siunitx_quantity_prefix_mode_tl :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 }
-    \siunitx_number_process:NN \l__siunitx_complex_img_tl \l__siunitx_complex_img_tl
-    \fp_set:Nn \l__siunitx_complex_tmp_fp
-     { \exp_after:wN \__siunitx_complex_extract_exp:nnnnnnn \l__siunitx_complex_img_tl }
-    \__siunitx_complex_drop_exp:N \l__siunitx_complex_real_tl
-    \__siunitx_complex_drop_exp:N \l__siunitx_complex_img_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_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
-    \exp_not:c { __siunitx_complex_format_extract-exponent:N }
-      \exp_not:N \l__siunitx_complex_img_tl
-    \exp_not:N \tl_if_empty:NF \exp_not:N \l__siunitx_complex_real_tl
-      {
-        \exp_not:c { __siunitx_complex_format_extract-exponent:N }
-          \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: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 } } }
-\cs_new_protected:Npn \__siunitx_complex_format_polar:n #1
-  {
-    \tl_if_blank:nTF {#1}
-      {
-        \bool_if:NT \l_siunitx_number_parse_bool
-          { \siunitx_number_process:NN \l__siunitx_complex_mag_tl \l__siunitx_complex_mag_tl }
-      }
-      {
-        \bool_if:NTF \l_siunitx_number_parse_bool
-          {
-            \use:c
-              { __siunitx_complex_format_polar_ \l_siunitx_quantity_prefix_mode_tl :n } {#1}
-          }
-          { \__siunitx_complex_format_polar_input:n {#1} }
-      }
-    \tl_set:Nx \l__siunitx_complex_tmp_tl
-      {
-        \bool_if:NTF \l_siunitx_number_parse_bool
-          { \siunitx_number_output:N \l__siunitx_complex_mag_tl }
-          { \exp_not:V \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
-  {
-    \bool_if:NT \l_siunitx_number_parse_bool
-      { \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 } ,
-    print-complex-unity   = false
-  }
-\cs_generate_variant:Nn \keys_set:nn { nx }
-\fp_new:N \l__siunitx_compound_tmp_fp
-\seq_new:N \l__siunitx_compound_tmp_seq
-\tl_new:N \l__siunitx_compound_tmp_tl
-\tl_new:N \l__siunitx_compound_first_tl
-\tl_new:N \l__siunitx_compound_exp_tl
-\tl_new:N \l__siunitx_compound_start_tl
-\tl_new:N \l__siunitx_compound_end_tl
-\int_new:N \l__siunitx_compound_count_int
-\bool_new:N \l__siunitx_compound_unit_bool
-\tl_new:N \l__siunitx_compound_unit_tl
-\tl_new:N \l__siunitx_compound_bracket_close_tl
-\tl_new:N \l__siunitx_compound_bracket_open_tl
-\tl_set:Nn \l__siunitx_compound_bracket_open_tl { ( }
-\tl_set:Nn \l__siunitx_compound_bracket_close_tl { ) }
-\bool_new:N \l__siunitx_compound_exp_bracket_bool
-\bool_new:N \l__siunitx_compound_exp_combine_bool
-\bool_new:N \l__siunitx_compound_separator_text_bool
-\bool_new:N \l__siunitx_compound_unit_bracket_bool
-\bool_new:N \l__siunitx_compound_unit_power_bool
-\bool_new:N \l__siunitx_compound_unit_repeat_bool
-\keys_define:nn { siunitx }
-  {
-    compound-exponents .choice: ,
-    compound-exponents / combine .code:n =
-      {
-        \bool_set_false:N \l__siunitx_compound_exp_bracket_bool
-        \bool_set_true:N \l__siunitx_compound_exp_combine_bool
-      } ,
-    compound-exponents / combine-bracket .code:n =
-      {
-        \bool_set_true:N \l__siunitx_compound_exp_bracket_bool
-        \bool_set_true:N \l__siunitx_compound_exp_combine_bool
-      } ,
-    compound-exponents / individual .code:n =
-      {
-        \bool_set_false:N \l__siunitx_compound_exp_bracket_bool
-        \bool_set_false:N \l__siunitx_compound_exp_combine_bool
-      } ,
-    compound-final-separator .tl_set:N =
-      \l__siunitx_compound_separator_final_tl ,
-    compound-pair-separator .tl_set:N =
-      \l__siunitx_compound_separator_pair_tl ,
-    compound-separator .tl_set:N =
-      \l__siunitx_compound_separator_tl ,
-    compound-separator-mode .choice: ,
-    compound-separator-mode / number .code:n =
-      { \bool_set_false:N \l__siunitx_compound_separator_text_bool } ,
-    compound-separator-mode / text .code:n =
-      { \bool_set_true:N \l__siunitx_compound_separator_text_bool } ,
-    compound-units .choice: ,
-    compound-units / bracket .code:n =
-      {
-        \bool_set_true:N  \l__siunitx_compound_unit_bracket_bool
-        \bool_set_false:N \l__siunitx_compound_unit_power_bool
-        \bool_set_false:N \l__siunitx_compound_unit_repeat_bool
-      } ,
-    compound-units / bracket-power .code:n =
-      {
-        \bool_set_true:N  \l__siunitx_compound_unit_bracket_bool
-        \bool_set_true:N  \l__siunitx_compound_unit_power_bool
-        \bool_set_false:N \l__siunitx_compound_unit_repeat_bool
-      } ,
-    compound-units / power .code:n =
-      {
-        \bool_set_false:N \l__siunitx_compound_unit_bracket_bool
-        \bool_set_true:N  \l__siunitx_compound_unit_power_bool
-        \bool_set_false:N \l__siunitx_compound_unit_repeat_bool
-      } ,
-    compound-units / repeat .code:n   =
-      {
-        \bool_set_false:N \l__siunitx_compound_unit_bracket_bool
-        \bool_set_false:N \l__siunitx_compound_unit_power_bool
-        \bool_set_true:N  \l__siunitx_compound_unit_repeat_bool
-      } ,
-    compound-units / single .code:n   =
-      {
-        \bool_set_false:N \l__siunitx_compound_unit_bracket_bool
-        \bool_set_false:N \l__siunitx_compound_unit_power_bool
-        \bool_set_false:N \l__siunitx_compound_unit_repeat_bool
-      }
-  }
-\cs_new_protected:Npn \siunitx_compound_number:n #1
-  {
-    \group_begin:
-      \bool_set_false:N \l__siunitx_compound_unit_bool
-      \__siunitx_compound_format:nn {#1} { }
-      \__siunitx_compound_print:N \siunitx_print_number:x
-    \group_end:
-  }
-\cs_new_protected:Npn \__siunitx_compound_format:nn #1#2
-  {
-    \seq_clear:N \l__siunitx_compound_tmp_seq
-    \bool_if:NTF \l_siunitx_number_parse_bool
-      {
-        \exp_args:Nxx \__siunitx_compound_format:nnn
-          { \tl_head:n {#1} }
-          { \tl_tail:n {#1} }
-          {#2}
-      }
-      { \tl_map_function:nN {#1} \__siunitx_compound_unparsed:n }
-  }
-\cs_new_protected:Npn \__siunitx_compound_format:nnn #1#2#3
-  {
-    \tl_if_blank:nTF {#1}
-      {
-        \tl_if_blank:nF {#2}
-          { \__siunitx_compound_format:nn {#2} {#3} }
-      }
-      { \__siunitx_compound_format_aux:nnn {#1} {#2} {#3} }
-  }
-\cs_new_protected:Npn \__siunitx_compound_format_aux:nnn #1#2#3
-  {
-    \siunitx_number_parse:nN {#1} \l__siunitx_compound_tmp_tl
-    \bool_if:NTF \l__siunitx_compound_unit_bool
-      { \__siunitx_compound_format_units:nn {#2} {#3} }
-      { \siunitx_number_process:NN \l__siunitx_compound_tmp_tl \l__siunitx_compound_first_tl }
-    \bool_lazy_and:nnTF
-      { \l__siunitx_compound_exp_combine_bool }
-      { \int_compare_p:nNn { \tl_count:n {#2} } > 0 }
-      { \__siunitx_compound_extract_exponents: }
-      {
-        \bool_if:NTF \l__siunitx_compound_unit_bool
-          {
-            \tl_set:Nx \l__siunitx_compound_tmp_tl
-              { \siunitx_number_output:NN \l__siunitx_compound_first_tl \q_nil }
-            \tl_set:Nx \l__siunitx_compound_tmp_tl
-              { \__siunitx_compound_uncert_bracket:N \l__siunitx_compound_tmp_tl }
-          }
-          {
-            \tl_set:Nx \l__siunitx_compound_tmp_tl
-              { \siunitx_number_output:N \l__siunitx_compound_first_tl }
-          }
-        \seq_put_right:NV \l__siunitx_compound_tmp_seq \l__siunitx_compound_tmp_tl
-      }
-    \tl_map_function:nN {#2} \__siunitx_compound_parsed:n
-  }
-\cs_new_protected:Npn \__siunitx_compound_extract_exponents:
-  {
-    \tl_set:Nx \l__siunitx_compound_tmp_tl
-      { \siunitx_number_output:NN \l__siunitx_compound_first_tl \q_nil }
-    \exp_after:wN \__siunitx_compound_extract_exponents_auxi:w
-      \l__siunitx_compound_tmp_tl \q_stop
-  }
-\cs_new_protected:Npn \__siunitx_compound_extract_exponents_auxi:w
-  #1 \q_nil #2 \q_nil #3 \q_nil #4 \q_nil #5 \q_nil #6 \q_nil #7 \q_nil #8
-  \q_nil #9 \q_stop
-  {
-    \__siunitx_compound_extract_exponents_auxii:nw {#1#2#3#4#5#6#7#8} #9 \q_stop
-  }
-\cs_new_protected:Npn \__siunitx_compound_extract_exponents_auxii:nw
-  #1#2 \q_nil #3 \q_nil #4 \q_stop
-  {
-    \seq_put_right:Nn \l__siunitx_compound_tmp_seq { #1#2 }
-    \tl_set:Nn \l__siunitx_compound_exp_tl { #3#4 }
-    \exp_after:wN \__siunitx_compound_extract_exponents_auxiii:nnnnnnn
-      \l__siunitx_compound_first_tl
-  }
-\cs_new_protected:Npn \__siunitx_compound_extract_exponents_auxiii:nnnnnnn
-  #1#2#3#4#5#6#7
-  {
-    \keys_set:nn { siunitx }
-      {
-        drop-exponent  = true  ,
-        exponent-mode  = fixed ,
-        fixed-exponent = #6#7
-      }
-  }
-\cs_new_protected:Npn \__siunitx_compound_parsed:n #1
-  {
-    \tl_if_blank:nF {#1}
-      { \__siunitx_compound_parsed_aux:n {#1} }
-  }
-\cs_new_protected:Npn \__siunitx_compound_parsed_aux:n #1
-  {
-    \bool_if:NTF \l__siunitx_compound_unit_bool
-      {
-        \siunitx_number_parse:nN {#1} \l__siunitx_compound_tmp_tl
-        \siunitx_number_process:NN \l__siunitx_compound_tmp_tl \l__siunitx_compound_tmp_tl
-        \tl_set:Nx \l__siunitx_compound_tmp_tl
-          { \siunitx_number_output:NN \l__siunitx_compound_tmp_tl \q_nil }
-        \tl_set:Nx \l__siunitx_compound_tmp_tl
-          { \__siunitx_compound_uncert_bracket:N \l__siunitx_compound_tmp_tl }
-      }
-      { \siunitx_number_format:nN {#1} \l__siunitx_compound_tmp_tl }
-    \seq_put_right:NV \l__siunitx_compound_tmp_seq \l__siunitx_compound_tmp_tl
-  }
-\cs_new_protected:Npn \__siunitx_compound_unparsed:n #1
-  {
-    \tl_if_blank:nF {#1}
-      { \seq_put_right:Nn \l__siunitx_compound_tmp_seq { \ensuremath {#1} } }
-  }
-\cs_new_protected:Npn \__siunitx_compound_format_units:nn #1#2
-  {
-    \bool_if:NTF \l__siunitx_compound_unit_power_bool
-      {
-        \use:c { __siunitx_compound_format_ \l_siunitx_quantity_prefix_mode_tl :nn }
-          {#2} { \tl_count:n {#1} + 1 }
-      }
-      {
-        \use:c { __siunitx_compound_format_ \l_siunitx_quantity_prefix_mode_tl :n } {#2}
-      }
-  }
-\cs_new_protected:cpx { __siunitx_compound_format_combine-exponent:n } #1
-  {
-    \exp_not:c { __siunitx_compound_format_combine-exponent_aux:n }
-      {
-        \exp_not:N \siunitx_unit_format_combine_exponent:nnN
-          {#1}
-      }
-  }
-\cs_new_protected:cpx { __siunitx_compound_format_combine-exponent:nn } #1#2
-  {
-    \exp_not:c { __siunitx_compound_format_combine-exponent_aux:n }
-      {
-        \exp_not:N \siunitx_unit_format_multiply_combine_exponent:nnnN
-          {#1} {#2}
-      }
-  }
-\cs_new_protected:cpn { __siunitx_compound_format_combine-exponent_aux:n } #1
-  {
-    \bool_set_true:N \l__siunitx_compound_exp_combine_bool
-    \siunitx_number_process:NN \l__siunitx_compound_tmp_tl \l__siunitx_compound_first_tl
-    \exp_args:NV \__siunitx_compound_extract_exp:nN
-      \l__siunitx_compound_first_tl \l__siunitx_compound_tmp_fp
-    #1 \l__siunitx_compound_tmp_fp \l__siunitx_compound_unit_tl
-  }
-\cs_new_protected:cpx { __siunitx_compound_format_extract-exponent:n } #1
-  {
-    \exp_not:c { __siunitx_compound_format_extract-exponent_aux:n }
-      { \exp_not:N \siunitx_unit_format_extract_prefixes:nNN {#1} }
-  }
-\cs_new_protected:cpx { __siunitx_compound_format_extract-exponent:nn } #1#2
-  {
-    \exp_not:c { __siunitx_compound_format_extract-exponent_aux:n }
-      {
-        \exp_not:N \siunitx_unit_format_multiply_extract_prefixes:nnNN
-          {#1} {#2}
-      }
-  }
-\cs_new_protected:cpn { __siunitx_compound_format_extract-exponent_aux:n } #1
-  {
-    #1 \l__siunitx_compound_unit_tl \l__siunitx_compound_tmp_fp
-    \tl_set:Nx \l__siunitx_compound_tmp_tl
-      { \siunitx_number_adjust_exponent:Nn \l__siunitx_compound_tmp_tl \l__siunitx_compound_tmp_fp }
-    \siunitx_number_process:NN \l__siunitx_compound_tmp_tl \l__siunitx_compound_first_tl
-    \bool_set_true:N \l__siunitx_compound_exp_combine_bool
-  }
-\cs_new_protected:Npn \__siunitx_compound_format_input:n #1
-  {
-    \siunitx_number_process:NN \l__siunitx_compound_tmp_tl \l__siunitx_compound_first_tl
-    \siunitx_unit_format:nN {#1} \l__siunitx_compound_unit_tl
-  }
-\cs_new_protected:Npn \__siunitx_compound_format_input:nn #1#2
-  {
-    \siunitx_number_process:NN \l__siunitx_compound_tmp_tl \l__siunitx_compound_first_tl
-    \siunitx_unit_format_multiply:nnN {#1} {#2} \l__siunitx_compound_unit_tl
-  }
-\cs_new_protected:Npn \__siunitx_compound_extract_exp:nN #1#2
-  { \__siunitx_compound_extract_exp:nnnnnnnN #1 #2 }
-\cs_new_protected:Npn \__siunitx_compound_extract_exp:nnnnnnnN #1#2#3#4#5#6#7#8
-  { \fp_set:Nn #8 {#6#7} }
-\cs_new_protected:Npn \siunitx_compound_quantity:nn #1#2
-  {
-    \group_begin:
-      \bool_if:NT \l__siunitx_compound_unit_bracket_bool
-        { \bool_set_true:N \l__siunitx_compound_exp_bracket_bool }
-      \bool_if:NT \l__siunitx_compound_unit_repeat_bool
-        { \bool_set_false:N \l__siunitx_compound_exp_combine_bool }
-      \bool_lazy_or:nnT
-        { \l__siunitx_compound_unit_bracket_bool }
-        { ! \l__siunitx_compound_unit_repeat_bool }
-        { \bool_set_false:N \l_siunitx_number_bracket_ambiguous_bool }
-      \bool_set_true:N \l__siunitx_compound_unit_bool
-      \__siunitx_compound_format:nn {#1} {#2}
-      \bool_if:NF \l_siunitx_number_parse_bool
-        { \siunitx_unit_format:nN {#2} \l__siunitx_compound_unit_tl }
-      \str_if_eq:VnT \l_siunitx_quantity_prefix_mode_tl { combine-exponent }
-        { \tl_clear:N \l__siunitx_compound_exp_tl }
-      \bool_if:NTF \l__siunitx_compound_unit_repeat_bool
-        { \__siunitx_compound_print:N \__siunitx_compound_print_quantity:x }
-        {
-          \bool_lazy_and:nnTF
-            { \l__siunitx_compound_unit_bracket_bool }
-            { \tl_if_empty_p:N \l__siunitx_compound_exp_tl }
-            {
-              \siunitx_print_number:V \l__siunitx_compound_bracket_open_tl
-              \__siunitx_compound_print:N \siunitx_print_number:x
-              \siunitx_print_number:V \l__siunitx_compound_bracket_close_tl
-            }
-            { \__siunitx_compound_print:N \siunitx_print_number:x }
-          \__siunitx_compound_print_quantity:n { \c_empty_tl }
-        }
-    \group_end:
-  }
-\cs_new_protected:Npn \__siunitx_compound_print:N #1
-  {
-    \bool_lazy_and:nnTF
-      { \l__siunitx_compound_exp_bracket_bool }
-      { ! \tl_if_empty_p:N \l__siunitx_compound_exp_tl }
-      {
-        \__siunitx_compound_print:xxN
-          { \exp_not:V \l__siunitx_compound_bracket_open_tl }
-          {
-            \exp_not:V \l__siunitx_compound_bracket_close_tl
-            \exp_not:V \l__siunitx_compound_exp_tl
-          }
-          #1
-      }
-      { \__siunitx_compound_print:xxN { } { \exp_not:V \l__siunitx_compound_exp_tl } #1 }
-  }
-\cs_new_protected:Npn \__siunitx_compound_print:nnN #1#2#3
-  {
-    \exp_args:Nx \__siunitx_compound_print:nnnN
-      { \seq_count:N \l__siunitx_compound_tmp_seq } {#1} {#2} #3
-  }
-\cs_generate_variant:Nn \__siunitx_compound_print:nnN { xx }
-\cs_new_protected:Npn \__siunitx_compound_print:nnnN #1#2#3#4
-  {
-    \int_case:nnF {#1}
-      {
-        { 0 } { }
-        { 1 }
-          {
-            #4
-              { \seq_item:Nn \l__siunitx_compound_tmp_seq { 1 } }
-          }
-        { 2 }
-          {
-            #4
-              {
-                \exp_not:n {#2}
-                \seq_item:Nn \l__siunitx_compound_tmp_seq { 1 }
-              }
-            \__siunitx_compound_print_separator:V \l__siunitx_compound_separator_pair_tl
-            #4
-              {
-                \seq_item:Nn \l__siunitx_compound_tmp_seq { 2 }
-                \exp_not:n {#3}
-              }
-          }
-      }
-      {
-        \int_set:Nn \l__siunitx_compound_count_int {#1}
-        \tl_set:Nn \l__siunitx_compound_start_tl {#2}
-        \tl_set:Nn \l__siunitx_compound_end_tl {#3}
-        \cs_set_eq:NN \__siunitx_compound_print_aux:n #4
-        \seq_map_indexed_function:NN
-          \l__siunitx_compound_tmp_seq
-          \__siunitx_compound_print_aux:nn
-      }
-  }
-\cs_new_protected:Npn \__siunitx_compound_print_aux:n #1 { }
-\cs_new_protected:Npn \__siunitx_compound_print_aux:nn #1#2
-  {
-    \int_case:nnF {#1}
-      {
-        { 1 }
-          {
-            \__siunitx_compound_print_aux:n
-              {
-                \exp_not:V \l__siunitx_compound_start_tl
-                \exp_not:n {#2}
-              }
-            \__siunitx_compound_print_separator:V \l__siunitx_compound_separator_tl
-          }
-        { \l__siunitx_compound_count_int - 1 }
-          {
-            \__siunitx_compound_print_aux:n { \exp_not:n {#2} }
-            \__siunitx_compound_print_separator:V \l__siunitx_compound_separator_final_tl
-          }
-        { \l__siunitx_compound_count_int }
-          {
-            \__siunitx_compound_print_aux:n
-              {
-                \exp_not:n {#2}
-                \exp_not:V \l__siunitx_compound_end_tl
-              }
-          }
-      }
-      {
-        \__siunitx_compound_print_aux:n { \exp_not:n {#2} }
-        \__siunitx_compound_print_separator:V \l__siunitx_compound_separator_tl
-      }
-  }
-\cs_new_protected:Npn \__siunitx_compound_print_quantity:n #1
-  { \siunitx_quantity_print:nV {#1} \l__siunitx_compound_unit_tl }
-\cs_generate_variant:Nn  \__siunitx_compound_print_quantity:n { x }
-\cs_new_protected:Npn \__siunitx_compound_print_separator:n #1
-  {
-    \bool_if:NTF \l__siunitx_compound_separator_text_bool
-      { #1 }
-      { \siunitx_print_number:n {#1} }
-  }
-\cs_generate_variant:Nn \__siunitx_compound_print_separator:n { V }
-\cs_new:Npn \__siunitx_compound_uncert_bracket:N #1
-  { \exp_after:wN \__siunitx_compound_uncert_bracket:w #1 \q_stop }
-\cs_new:Npn \__siunitx_compound_uncert_bracket:w
-  #1 \q_nil #2 \q_nil #3 \q_nil #4 \q_nil #5 \q_nil #6 \q_nil #7 \q_nil
-  #8 \q_nil #9 \q_stop
-  { \__siunitx_compound_uncert_bracket:nnw {#1#2#3#4#5#6} {#7#8} #9 \q_stop }
-\cs_new:Npn \__siunitx_compound_uncert_bracket:nnw #1#2 #3 \q_nil #4 \q_nil #5 \q_stop
-  {
-    \bool_lazy_or:nnTF
-      { \tl_if_blank_p:n {#2#3} }
-      { ! \tl_if_blank_p:n {#5} }
-      { \exp_not:n {#1#2#3#4#5} }
-      {
-        \exp_not:V \l__siunitx_compound_bracket_open_tl
-        \exp_not:n {#1#2#3}
-        \exp_not:V \l__siunitx_compound_bracket_close_tl
-        \exp_not:n {#4#5}
-      }
-  }
-\tl_new:N \l__siunitx_list_exp_tl
-\tl_new:N \l__siunitx_list_units_tl
-\keys_define:nn { siunitx }
-  {
-    list-exponents .choices:nn =
-      { combine , combine-bracket , individual }
-      { \tl_set_eq:NN \l__siunitx_list_exp_tl \l_keys_choice_tl } ,
-    list-final-separator .tl_set:N = \l_siunitx_list_separator_final_tl ,
-    list-pair-separator .tl_set:N = \l_siunitx_list_separator_pair_tl ,
-    list-separator .tl_set:N = \l_siunitx_list_separator_tl ,
-    list-units .choices:nn =
-      { bracket , repeat , single }
-      { \tl_set_eq:NN \l__siunitx_list_units_tl \l_keys_choice_tl }
-  }
-\cs_new_protected:Npn \siunitx_number_list:nn #1
-  {
-    \group_begin:
-      \__siunitx_list_aux:
-      \siunitx_compound_number:n {#1}
-    \group_end:
-  }
-\cs_new_protected:Npn \siunitx_quantity_list:nn #1#2
-  {
-    \group_begin:
-      \__siunitx_list_aux:
-      \siunitx_compound_quantity:nn {#1} {#2}
-    \group_end:
-  }
-\cs_new_protected:Npn \__siunitx_list_aux:
-  {
-    \keys_set:nx { siunitx }
-      {
-        compound-exponents       = \l__siunitx_list_exp_tl ,
-        compound-final-separator =
-          { \exp_not:V \l_siunitx_list_separator_final_tl } ,
-        compound-pair-separator  =
-          { \exp_not:V \l_siunitx_list_separator_pair_tl } ,
-        compound-separator       =
-          { \exp_not:V \l_siunitx_list_separator_tl } ,
-        compound-separator-mode  = text ,
-        compound-units           = \l__siunitx_list_units_tl
-      }
-  }
-\tl_new:N \l__siunitx_product_exp_tl
-\bool_new:N \l__siunitx_product_phrase_bool
-\tl_new:N \l__siunitx_product_units_tl
-\keys_define:nn { siunitx }
-  {
-    product-exponents .choices:nn =
-      { combine , combine-bracket , individual }
-      { \tl_set_eq:NN \l__siunitx_product_exp_tl \l_keys_choice_tl } ,
-    product-mode .choice: ,
-    product-mode / phrase .code:n =
-      { \bool_set_true:N \l__siunitx_product_phrase_bool } ,
-    product-mode / symbol .code:n =
-      { \bool_set_false:N \l__siunitx_product_phrase_bool } ,
-    product-phrase .tl_set:N = \l__siunitx_product_phrase_tl ,
-    product-symbol .tl_set:N = \l__siunitx_product_symbol_tl ,
-    product-units .choices:nn =
-      { bracket , bracket-power , power , repeat , single }
-      { \tl_set_eq:NN \l__siunitx_product_units_tl \l_keys_choice_tl }
-  }
-\cs_new_protected:Npn \siunitx_number_product:n #1
-  {
-    \group_begin:
-      \__siunitx_product_aux:
-      \siunitx_compound_number:n {#1}
-    \group_end:
-  }
-\cs_new_protected:Npn \siunitx_quantity_product:nn #1#2
-  {
-    \group_begin:
-      \__siunitx_product_aux:
-      \siunitx_compound_quantity:nn {#1} {#2}
-    \group_end:
-  }
-\cs_new_protected:Npn \__siunitx_product_aux:
-  {
-    \bool_if:NTF \l__siunitx_product_phrase_bool
-      { \__siunitx_product_aux:x { \exp_not:V \l__siunitx_product_phrase_tl } }
-      { \__siunitx_product_aux:x { { } \exp_not:V \l__siunitx_product_symbol_tl { } } }
-  }
-\cs_new_protected:Npn \__siunitx_product_aux:n #1
-  {
-    \keys_set:nx { siunitx }
-      {
-        compound-exponents       = \l__siunitx_product_exp_tl ,
-        compound-final-separator = { \exp_not:n {#1} } ,
-        compound-pair-separator  = { \exp_not:n {#1} } ,
-        compound-separator       = { \exp_not:n {#1} } ,
-        compound-separator-mode  =
-          \bool_if:NTF \l__siunitx_product_phrase_bool { text } { number } ,
-        compound-units           = \l__siunitx_product_units_tl
-      }
-  }
-\cs_generate_variant:Nn \__siunitx_product_aux:n { x }
-\tl_new:N \l__siunitx_range_exp_tl
-\tl_new:N \l__siunitx_range_units_tl
-\keys_define:nn { siunitx }
-  {
-    range-exponents .choices:nn =
-      { combine , combine-bracket , individual }
-      { \tl_set_eq:NN \l__siunitx_range_exp_tl \l_keys_choice_tl } ,
-    range-phrase .tl_set:N = \l_siunitx_range_phrase_tl ,
-    range-units .choices:nn =
-      { bracket , repeat , single }
-      { \tl_set_eq:NN \l__siunitx_range_units_tl \l_keys_choice_tl }
-  }
-\cs_new_protected:Npn \siunitx_number_range:nn #1#2
-  {
-    \group_begin:
-      \__siunitx_range_aux:
-      \siunitx_compound_number:n { {#1} {#2} }
-    \group_end:
-  }
-\cs_new_protected:Npn \siunitx_quantity_range:nnn #1#2#3
-  {
-    \group_begin:
-      \__siunitx_range_aux:
-      \siunitx_compound_quantity:nn { {#1} {#2} } {#3}
-    \group_end:
-  }
-\cs_new_protected:Npn \__siunitx_range_aux:
-  {
-    \keys_set:nx { siunitx }
-      {
-        compound-exponents       = \l__siunitx_range_exp_tl ,
-        compound-pair-separator  = { \exp_not:V \l_siunitx_range_phrase_tl } ,
-        compound-separator-mode  = text ,
-        compound-units           = \l__siunitx_range_units_tl
-      }
-  }
-\keys_set:nn { siunitx }
-  {
-    compound-exponents       = individual  ,
-    compound-final-separator =
-      {
-        \ifmmode \  \else \space \fi
-        \text { and }
-        \ifmmode \  \else \space \fi
-      } ,
-    compound-pair-separator  =
-      {
-        \ifmmode \  \else \space \fi
-        \text { and }
-        \ifmmode \  \else \space \fi
-      } ,
-    compound-separator       =
-      { , \ifmmode \  \else \space \fi } ,
-    compound-separator-mode  = text        ,
-    compound-units           = repeat      ,
-    list-exponents           = individual  ,
-    list-final-separator     =
-      {
-        \ifmmode \  \else \space \fi
-        \text { and }
-        \ifmmode \  \else \space \fi
-      } ,
-    list-pair-separator      =
-      {
-        \ifmmode \  \else \space \fi
-        \text { and }
-        \ifmmode \  \else \space \fi
-      } ,
-    list-separator           =
-      { , \ifmmode \  \else \space \fi } ,
-    list-units               = repeat      ,
-    product-exponents        = individual  ,
-    product-mode             = symbol      ,
-    product-phrase           =
-      {
-        \ifmmode \  \else \space \fi
-        \text { by }
-        \ifmmode \  \else \space \fi
-      } ,
-    product-symbol           = \times      ,
-    product-units            = repeat      ,
-    range-exponents          = individual  ,
-    range-phrase             =
-      {
-        \ifmmode \  \else \space \fi
-        \text { to }
-        \ifmmode \  \else \space \fi
-      } ,
-    range-units              = repeat
-  }
-\keys_define:nn { siunitx }
-  {
-    locale .choice: ,
-    locale / DE .meta:n =
-      {
-        exponent-product      = \cdot ,
-        inter-unit-product    = \,    ,
-        output-decimal-marker = { , }
-      } ,
-    locale / FR .meta:n =
-      {
-        exponent-product      = \times ,
-        inter-unit-product    = \,     ,
-        output-decimal-marker = { , }
-      } ,
-    locale / PL .meta:n =
-      {
-        exponent-product      = \cdot ,
-        inter-unit-product    = \cdot ,
-        output-decimal-marker = { , }
-      } ,
-    locale / SI .meta:n =
-      {
-        exponent-product      = \times ,
-        inter-unit-product    = \,     ,
-        output-decimal-marker = { , }
-      } ,
-    locale / UK .meta:n =
-      {
-        exponent-product      = \times ,
-        inter-unit-product    = \,     ,
-        output-decimal-marker = .
-      },
-    locale / US .meta:n =
-      {
-        exponent-product      = \times ,
-        inter-unit-product    = \,     ,
-        output-decimal-marker = .
-      } ,
-    locale / ZA .meta:n =
-      {
-        exponent-product      = \times ,
-        inter-unit-product    = \cdot  ,
-        output-decimal-marker = { , }
-      }
-  }
-\file_if_exist:nT { translations.sty }
-  {
-    \RequirePackage { translations }
-    \DeclareTranslation { Catalan }    { and } { i }
-    \DeclareTranslation { Portuguese } { and } { e }
-    \DeclareTranslation { Slovene }    { and } { in }
-    \DeclareTranslation { Brazilian }  { to~(numerical~range) } { a }
-    \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 { Portuguese } { to~(numerical~range) } { a }
-    \DeclareTranslation { Slovene }    { to~(numerical~range) } { do }
-    \DeclareTranslation { Spanish }    { to~(numerical~range) } { a }
-    \keys_set:nn { siunitx }
-      {
-        list-final-separator =
-          {
-            \ifmmode \  \else \space \fi
-            \text { \GetTranslation { and } }
-            \ifmmode \  \else \space \fi
-          } ,
-        list-pair-separator  =
-          {
-            \ifmmode \  \else \space \fi
-            \text { \GetTranslation { and } }
-            \ifmmode \  \else \space \fi
-          } ,
-        range-phrase         =
-          {
-            \ifmmode \  \else \space \fi
-            \text { \GetTranslation { to~(numerical~range) } }
-            \ifmmode \  \else \space \fi
-          }
-      }
-  }
 \cs_generate_variant:Nn \tl_if_blank:nTF { f }
 \cs_generate_variant:Nn \tl_if_blank_p:n { f }
 \cs_generate_variant:Nn \tl_if_in:NnTF { NV }
@@ -1849,6 +122,8 @@
               { \tl_put_right:Nn \l_siunitx_number_input_sign_tl {##1} }
           }
       } ,
+    input-uncertainty-divider .tl_set:N =
+      \l__siunitx_number_input_uncert_divide_tl ,
     parse-numbers .bool_set:N =
       \l_siunitx_number_parse_bool ,
     retain-explicit-decimal-marker .bool_set:N =
@@ -1869,7 +144,10 @@
 \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_tolerance_tl
 \tl_new:N \l__siunitx_number_uncert_tl
+\int_new:N \l__siunitx_number_uncert_offset_int
+\tl_new:N \l__siunitx_number_uncert_types_tl
 \bool_new:N \l__siunitx_number_validate_bool
 \cs_new_protected:Npn \siunitx_number_normalize_symbols:N #1
   {
@@ -1914,6 +192,7 @@
     \group_begin:
       \tl_clear:N \l__siunitx_number_parsed_tl
       \tl_clear:N \l__siunitx_number_uncert_tl
+      \tl_clear:N \l__siunitx_number_uncert_types_tl
       \tl_map_inline:Nn \l__siunitx_number_input_ignore_tl
         {
           \token_if_macro:NT ##1
@@ -2286,7 +565,6 @@
 \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
-    \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
@@ -2335,6 +613,7 @@
   {
     \tl_clear:N \l__siunitx_number_flex_tl
     \tl_clear:N \l__siunitx_number_parsed_tl
+    \tl_clear:N \l__siunitx_number_uncert_tl
   }
 \cs_new_protected:Npn \__siunitx_number_parse_sign:
   {
@@ -2394,7 +673,7 @@
       {
         \tl_if_in:NnTF \l_siunitx_number_input_decimal_tl {#1}
           { \__siunitx_number_parse_uncert_marker: }
-          { \__siunitx_number_parse_loop_break:w }
+          { \__siunitx_number_parse_uncert_auxiv:N #1 }
       }
   }
 \cs_new_protected:Npn \__siunitx_number_parse_uncert_auxii:N #1
@@ -2404,7 +683,7 @@
         \__siunitx_number_parse_uncert_auxiii:
         \__siunitx_number_parse_uncert_after:N
       }
-      { \__siunitx_number_parse_loop_break:w }
+      { \__siunitx_number_parse_uncert_auxiv:N #1 }
   }
 \cs_new_protected:Npn \__siunitx_number_parse_uncert_auxiii:
   {
@@ -2413,6 +692,20 @@
       { \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_auxiv:N #1
+  {
+    \tl_if_empty:NTF \l__siunitx_number_tolerance_tl
+      {
+        \tl_if_in:NnTF \l__siunitx_number_input_uncert_divide_tl {#1}
+          {
+            \cs_set_eq:NN \l__siunitx_number_tolerance_tl \l__siunitx_number_partial_tl
+            \tl_clear:N \l__siunitx_number_partial_tl
+            \__siunitx_number_parse_uncert:N
+          }
+          { \__siunitx_number_parse_loop_break:w }
+      }
+      { \__siunitx_number_parse_loop_break:w }
+  }
 \cs_new_protected:Npn \__siunitx_number_parse_uncert_marker:
   {
     \exp_after:wN \__siunitx_number_parse_uncert_marker:nnn
@@ -2447,18 +740,57 @@
 \cs_new_protected:Npn \__siunitx_number_parse_uncert_marker:w { }
 \cs_new_protected:Npn \__siunitx_number_parse_uncert_marker:nnnnN #1#2#3#4#5
   {
+    \tl_set:Nx \l__siunitx_number_tmp_tl { \tl_head:V \l__siunitx_number_input_uncert_divide_tl }
+    \tl_if_empty:NTF \l__siunitx_number_tmp_tl
+      { \__siunitx_number_parse_uncert_marker:nnnnnN {#1} {#2} {#3} {#4} { } #5 }
+      {
+        \use:x
+          {
+            \cs_set_protected:Npn \exp_not:N \__siunitx_number_parse_uncert_marker:w
+              ####1 \l__siunitx_number_tmp_tl ####2 \l__siunitx_number_tmp_tl ####3 \exp_not:N \q_stop
+              {
+                \exp_not:N \tl_if_blank:nTF {####2}
+                  {
+                    \__siunitx_number_parse_uncert_marker:nnnnnN
+                      \exp_not:n { {#1} {#2} {#3} }
+                      {####1} { }
+                  }
+                  {
+                    \__siunitx_number_parse_uncert_marker:nnnnnN
+                      \exp_not:n { {#1} {#2} {#3} }
+                      {####1} { \l__siunitx_number_tmp_tl ####2 }
+                  }
+                    \exp_not:N #5
+              }
+             \exp_not:N \__siunitx_number_parse_uncert_marker:w #4
+               \l__siunitx_number_tmp_tl \l__siunitx_number_tmp_tl \exp_not:N \q_stop
+          }
+      }
+  }
+\cs_new_protected:Npn \__siunitx_number_parse_uncert_marker:nnnnnN #1#2#3#4#5#6
+  {
+    \exp_args:Ne \__siunitx_number_parse_uncert_marker:nnnnnnN
+      { \int_eval:n { \tl_count:n {#4} } }
+      {#1} {#2} {#3} {#4} {#5} #6
+  }
+\cs_new_protected:Npn \__siunitx_number_parse_uncert_marker:nnnnnnN #1#2#3#4#5#6#7
+  {
+    \bool_lazy_and:nnF
+      { \tl_if_empty_p:N \l__siunitx_number_tolerance_tl }
+      { \tl_if_empty_p:N \l__siunitx_number_uncert_types_tl }
+      {
+        \int_compare:nNnF {#1} = \l__siunitx_number_uncert_offset_int
+          { \__siunitx_number_parse_loop_break:w }
+      }
+    \int_set:Nn \l__siunitx_number_uncert_offset_int {#1}
     \tl_set:Nx \l__siunitx_number_parsed_tl
       {
-         {#1}
          {#2}
+         {#3}
          {
-           #3
+           #4
            \prg_replicate:nn
-             {
-               \int_max:nn
-                 { 0 }
-                 { \tl_count:n {#4} - \tl_count:n {#3} }
-             }
+             { \int_max:nn { 0 } { #1 - \tl_count:n {#4} } }
              { 0 }
          }
       }
@@ -2471,7 +803,7 @@
         \__siunitx_number_parse_uncert:NNN \c_true_bool
           \__siunitx_number_parse_uncert_auxii:N
       }
-        #4#5
+        #5#6#7
   }
 \cs_new_protected:Npn \__siunitx_number_parse_uncert_after:N #1
   {
@@ -2479,9 +811,26 @@
       {
         \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_if_empty:NTF \l__siunitx_number_tolerance_tl
+                { \exp_not:V \l__siunitx_number_partial_tl }
+                {
+                  { \exp_not:V \l__siunitx_number_tolerance_tl }
+                  { \exp_not:V \l__siunitx_number_partial_tl }
+                }
+              }
+          }
       }
+    \tl_set:Nx \l__siunitx_number_uncert_types_tl
+      {
+        \l__siunitx_number_uncert_types_tl
+        \tl_if_empty:NTF \l__siunitx_number_tolerance_tl
+          { S }
+          { A }
+      }
     \tl_clear:N \l__siunitx_number_partial_tl
+    \tl_clear:N \l__siunitx_number_tolerance_tl
     \quark_if_recursion_tail_stop_do:Nn #1
       {
         \tl_set:Nx \l__siunitx_number_parsed_tl
@@ -2490,11 +839,7 @@
             {
               \tl_if_empty:NF \l__siunitx_number_uncert_tl
                 {
-                  {
-                    \prg_replicate:nn
-                      { \tl_count:N \l__siunitx_number_uncert_tl }
-                     { S }
-                  }
+                  { \l__siunitx_number_uncert_types_tl }
                   \exp_not:V \l__siunitx_number_uncert_tl
                 }
             }
@@ -2501,6 +846,7 @@
           }
         \tl_clear:N \l__siunitx_number_partial_tl
         \tl_clear:N \l__siunitx_number_uncert_tl
+        \int_zero:N \l__siunitx_number_uncert_offset_int
       }
     \tl_if_in:NnTF \l__siunitx_number_input_uncert_open_tl {#1}
       { \__siunitx_number_parse_uncert:N }
@@ -2525,6 +871,9 @@
       \l__siunitx_number_min_decimal_int ,
     minimum-integer-digits .int_set:N =
       \l__siunitx_number_min_integer_int ,
+    round-direction .choices:nn =
+      { down , nearest , up }
+      { \tl_set_eq:NN \l__siunitx_number_round_dir_tl \l_keys_choice_tl } ,
     round-half .choice: ,
     round-half / even .code:n =
       { \bool_set_true:N \l__siunitx_number_round_half_even_bool } ,
@@ -2540,11 +889,16 @@
     round-precision .int_set:N =
       \l__siunitx_number_round_precision_int ,
     round-zero-positive .bool_set:N =
-      \l__siunitx_number_round_positive_bool
+      \l__siunitx_number_round_positive_bool ,
+    uncertainty-round-direction .choices:nn =
+      { down , nearest , up }
+      { \tl_set_eq:NN \l__siunitx_number_round_uncert_dir_tl \l_keys_choice_tl } ,
   }
 \bool_new:N \l__siunitx_number_round_half_even_bool
 \tl_new:N \l__siunitx_number_exponent_mode_tl
+\tl_new:N \l__siunitx_number_round_dir_tl
 \tl_new:N \l__siunitx_number_round_mode_tl
+\tl_new:N \l__siunitx_number_round_uncert_dir_tl
 \tl_new:N \l__siunitx_number_round_min_tl
 \cs_new_protected:Npn \__siunitx_number_set_round_min:n #1
   {
@@ -2988,56 +1342,62 @@
   }
 \cs_new:Npn \__siunitx_number_round:nnn #1#2#3
   {
-    \__siunitx_number_round_auxi:nnnN {#1} {#2} { }
-      #3 \q_recursion_tail \q_recursion_stop
+    \__siunitx_number_round:Vnnn \l__siunitx_number_round_dir_tl
+      {#1} {#2} {#3}
   }
 \cs_generate_variant:Nn \__siunitx_number_round:nnn { f }
-\cs_new:Npn \__siunitx_number_round_auxi:nnnN #1#2#3#4
+\cs_new:Npn \__siunitx_number_round:nnnn #1#2#3#4
   {
-    \quark_if_recursion_tail_stop_do:Nn #4
+    \__siunitx_number_round_auxi:nnnnN {#1} {#2} {#3} { }
+      #4 \q_recursion_tail \q_recursion_stop
+  }
+\cs_generate_variant:Nn \__siunitx_number_round:nnnn { V }
+\cs_new:Npn \__siunitx_number_round_auxi:nnnnN #1#2#3#4#5
+  {
+    \quark_if_recursion_tail_stop_do:Nn #5
       {
-        \__siunitx_number_round_auxii:nnnN {#1} {#3} { } #2
+        \__siunitx_number_round_auxii:nnnnN {#1} {#2} {#4} { } #3
           \q_recursion_tail \q_recursion_stop
       }
-    \__siunitx_number_round_auxi:nnnN {#1} {#2} {#4#3}
+    \__siunitx_number_round_auxi:nnnnN {#1} {#2} {#3} {#5#4}
   }
-\cs_new:Npn \__siunitx_number_round_auxii:nnnN #1#2#3#4
+\cs_new:Npn \__siunitx_number_round_auxii:nnnnN #1#2#3#4#5
   {
-    \quark_if_recursion_tail_stop_do:Nn #4
+    \quark_if_recursion_tail_stop_do:Nn #5
       {
-        \tl_if_blank:nTF {#2}
+        \tl_if_blank:nTF {#3}
           {
-            \__siunitx_number_round_auxiv:nnnN {#1} { } { } #3
+            \__siunitx_number_round_auxiv:nnnnN {#2} {#1} { } { } #4
               \q_recursion_tail \q_recursion_stop
           }
           {
-            \__siunitx_number_round_auxiii:nnnN {#1} {#3} { } #2
+            \__siunitx_number_round_auxiii:nnnnN {#2} {#1} {#4} { } #3
               \q_recursion_tail \q_recursion_stop
           }
       }
-    \__siunitx_number_round_auxii:nnnN {#1} {#2} {#4#3}
+    \__siunitx_number_round_auxii:nnnnN {#1} {#2} {#3} {#5#4}
   }
-\cs_new:Npn \__siunitx_number_round_auxiii:nnnN #1#2#3#4
+\cs_new:Npn \__siunitx_number_round_auxiii:nnnnN #1#2#3#4#5
   {
-    \quark_if_recursion_tail_stop_do:Nn #4
+    \quark_if_recursion_tail_stop_do:Nn #5
       {
-        \__siunitx_number_round_auxiv:nnnN {#1} { } {#3} #2
+        \__siunitx_number_round_auxiv:nnnnN {#1} {#2} { } {#4} #3
           \q_recursion_tail \q_recursion_stop
       }
     \int_compare:nNnTF {#1} > 0
       {
-        \exp_args:Nf \__siunitx_number_round_auxiii:nnnN
-          { \int_eval:n { #1 - 1 } } {#2} { #4#3 }
+        \exp_args:Nf \__siunitx_number_round_auxiii:nnnnN
+          { \int_eval:n { #1 - 1 } } {#2} {#3} { #5#4 }
       }
-      { \__siunitx_number_round_auxv:nnN {#3} {#2} #4 }
+      { \__siunitx_number_round_auxv:nnnN {#2} {#4} {#3} #5 }
   }
-\cs_new:Npn \__siunitx_number_round_auxiv:nnnN #1#2#3#4
+\cs_new:Npn \__siunitx_number_round_auxiv:nnnnN #1#2#3#4#5
   {
-    \quark_if_recursion_tail_stop_do:Nn #4
+    \quark_if_recursion_tail_stop_do:Nn #5
       {
         \int_compare:nNnTF {#1} = 0
           {
-            \__siunitx_number_round_auxvi:nnN {#3} {#2}
+            \__siunitx_number_round_auxvi:nnnN {#2} {#4} {#3}
               0 \q_recursion_tail \q_recursion_stop
           }
           { { 0 } { } }
@@ -3044,42 +1404,49 @@
       }
     \int_compare:nNnTF {#1} > 0
       {
-        \exp_args:Nf \__siunitx_number_round_auxiv:nnnN
-          { \int_eval:n { #1 - 1 } } { #2 0 } { #4#3 }
+        \exp_args:Nf \__siunitx_number_round_auxiv:nnnnN
+          { \int_eval:n { #1 - 1 } } {#2} { #3 0 } { #5#4 }
       }
-      { \__siunitx_number_round_auxvi:nnN {#3} {#2} #4 }
+      { \__siunitx_number_round_auxvi:nnnN {#2} {#4} {#3} #5 }
   }
-\cs_new:Npn \__siunitx_number_round_auxv:nnN #1#2#3
+\cs_new:Npn \__siunitx_number_round_auxv:nnnN #1#2#3#4
   {
-    \quark_if_recursion_tail_stop_do:Nn #3
+    \quark_if_recursion_tail_stop_do:Nn #4
       {
-        \__siunitx_number_round_auxvi:nnN
-          {#1} { } #2 \q_recursion_tail \q_recursion_stop
+        \__siunitx_number_round_auxvi:nnnN
+          {#1} {#2} { } #3 \q_recursion_tail \q_recursion_stop
       }
-    \__siunitx_number_round_auxvii:nnTF {#1} {#3}
+    \__siunitx_number_round_auxvii:nnnTF {#1} {#2} {#4}
       { \__siunitx_number_round_final_decimal:nnw }
       { \__siunitx_number_round_auxviii:nnN }
-        {#2} { } #3
+        {#3} { } #4
   }
-\cs_new:Npn \__siunitx_number_round_auxvi:nnN #1#2#3
+\cs_new:Npn \__siunitx_number_round_auxvi:nnnN #1#2#3#4
   {
-    \quark_if_recursion_tail_stop_do:Nn #3
+    \quark_if_recursion_tail_stop_do:Nn #4
       { { 0 } { } }
-    \__siunitx_number_round_auxvii:nnTF {#1} {#3}
+    \__siunitx_number_round_auxvii:nnnTF {#1} {#2} {#4}
       { \__siunitx_number_round_final_integer:nnw }
       { \__siunitx_number_round_auxix:nnN }
-        { } {#2} #3
+        { } {#3} #4
   }
-\cs_new:Npn \__siunitx_number_round_auxvii:nnTF #1#2
+\cs_new:Npn \__siunitx_number_round_auxvii:nnnTF #1#2#3
   {
-    \bool_lazy_or:nnTF
-      { \int_compare_p:nNn { 0 \tl_head:n {#1} } < 5 }
+    \str_case:nnF {#1}
       {
-        \bool_lazy_all_p:n
+        { down } { \use_i:nn }
+        { up }   { \use_ii:nn }
+      }
+      {
+        \bool_lazy_or:nnTF
+          { \int_compare_p:nNn { 0 \tl_head:n {#2} } < 5 }
           {
-            { \l__siunitx_number_round_half_even_bool }
-            { ! \int_if_odd_p:n {#2} }
-            { \__siunitx_number_round_if_half_p:n {#1} }
+            \bool_lazy_all_p:n
+              {
+                { \l__siunitx_number_round_half_even_bool }
+                { ! \int_if_odd_p:n {#3} }
+                { \__siunitx_number_round_if_half_p:n {#2} }
+              }
           }
       }
   }
@@ -3449,8 +1816,9 @@
     \use:e
       {
         \exp_not:N \__siunitx_number_round_uncertainty:nnnnnn
-          \__siunitx_number_round:nnn {#1} { } {#4}
-          {#2} {#3} {#1} {#4}
+          \__siunitx_number_round:Vnnn
+            \l__siunitx_number_round_uncert_dir_tl {#1} { } {#4}
+            {#2} {#3} {#1} {#4}
       }
   }
 \cs_new:Npn \__siunitx_number_round_uncertainty:nnnnnn #1#2#3#4#5#6
@@ -4150,6 +2518,7 @@
   \__siunitx_number_output_uncert_A:nnnn
 \cs_new:Npx \__siunitx_number_output_uncert_A:nnnnn #1#2#3#4#5
   {
+    { }
     ^
       {
         +
@@ -4421,6 +2790,7 @@
     retain-explicit-plus             = false                                  ,
     retain-negative-zero             = false                                  ,
     retain-zero-uncertainty          = false                                  ,
+    round-direction                  = nearest                                ,
     round-half                       = up                                     ,
     round-minimum                    = 0                                      ,
     round-mode                       = none                                   ,
@@ -4432,12 +2802,1880 @@
     uncertainty-descriptor-separator = \                                      ,
     uncertainty-descriptors          =                                        ,
     uncertainty-mode                 = compact                                ,
+    uncertainty-round-direction      = nearest                                ,
     uncertainty-separator            =                                        ,
     zero-decimal-as-symbol           = false                                  ,
     zero-symbol                      = \mbox { --- }
   }
 \keys_set:nx { siunitx }
-   { exponent-thresholds = -3 \c_colon_str 3 }
+  {
+    exponent-thresholds       = -3 \c_colon_str 3 ,
+    input-uncertainty-divider = \c_colon_str
+  }
+\bool_new:N \l__siunitx_angle_tmp_bool
+\dim_new:N \l__siunitx_angle_tmp_dim
+\tl_new:N \l__siunitx_angle_tmp_tl
+\keys_define:nn { siunitx }
+  {
+    angle-mode .choice: ,
+    angle-mode / arc .code:n =
+      {
+        \bool_set_true:N \l__siunitx_angle_force_arc_bool
+        \bool_set_false:N \l__siunitx_angle_force_decimal_bool
+      } ,
+    angle-mode / decimal .code:n =
+      {
+        \bool_set_false:N \l__siunitx_angle_force_arc_bool
+        \bool_set_true:N \l__siunitx_angle_force_decimal_bool
+      } ,
+    angle-mode / input .code:n =
+      {
+        \bool_set_false:N \l__siunitx_angle_force_arc_bool
+        \bool_set_false:N \l__siunitx_angle_force_decimal_bool
+      } ,
+    angle-symbol-degree .tl_set:N =
+      \l__siunitx_angle_symbol_degree_tl ,
+    angle-symbol-minute .tl_set:N =
+      \l__siunitx_angle_symbol_minute_tl ,
+    angle-symbol-second .tl_set:N =
+      \l__siunitx_angle_symbol_second_tl ,
+    angle-symbol-over-decimal .bool_set:N =
+      \l__siunitx_angle_astronomy_bool ,
+    angle-separator .tl_set:N =
+      \l__siunitx_angle_separator_tl ,
+    fill-angle-degrees .bool_set:N =
+      \l__siunitx_angle_fill_degrees_bool ,
+    fill-angle-minutes .bool_set:N =
+      \l__siunitx_angle_fill_minutes_bool ,
+    fill-angle-seconds .bool_set:N =
+      \l__siunitx_angle_fill_seconds_bool ,
+    number-angle-product .tl_set:N =
+      \l__siunitx_angle_product_tl
+  }
+\bool_new:N \l__siunitx_angle_force_arc_bool
+\bool_new:N \l__siunitx_angle_force_decimal_bool
+\cs_new_protected:Npn \siunitx_angle:n #1
+  {
+    \bool_if:NTF \l_siunitx_number_parse_bool
+      { \__siunitx_angle_angle:n {#1} }
+      {
+        \tl_if_blank:nF {#1}
+          {
+            \tl_set:Nn \l__siunitx_angle_degrees_tl { \ensuremath {#1} }
+            \__siunitx_angle_arc_print:VVV
+              \l__siunitx_angle_degrees_tl
+              \c_empty_tl
+              \c_empty_tl
+          }
+      }
+  }
+\cs_new_protected:Npn \__siunitx_angle_angle:n #1
+  {
+    \bool_if:NTF \l__siunitx_angle_force_arc_bool
+      { \exp_args:Ne \__siunitx_angle_arc_convert:n { \fp_eval:n {#1} } }
+      {
+        \siunitx_number_parse:nN {#1} \l__siunitx_angle_degrees_tl
+        \siunitx_number_process:NN \l__siunitx_angle_degrees_tl \l__siunitx_angle_degrees_tl
+        \tl_set:Nx \l__siunitx_angle_degrees_tl
+          { \siunitx_number_output:NN \l__siunitx_angle_degrees_tl \q_nil }
+        \__siunitx_angle_arc_print:VVV
+          \l__siunitx_angle_degrees_tl
+          \c_empty_tl
+          \c_empty_tl
+      }
+  }
+\cs_new_protected:Npn \siunitx_angle:nnn #1#2#3
+  {
+    \bool_if:NTF \l_siunitx_number_parse_bool
+      {
+        \bool_if:NTF \l__siunitx_angle_force_decimal_bool
+          {
+            \exp_args:Ne \siunitx_angle:n
+              { \fp_eval:n { #1 + (#2) / 60 + (#3) / 3600 } }
+          }
+          { \__siunitx_angle_arc_sign:nnn {#1} {#2} {#3} }
+      }
+      {
+        \tl_set:Nx \l__siunitx_angle_degrees_tl
+          { \tl_if_blank:nF {#1} { \exp_not:n { \ensuremath {#1} } } }
+        \tl_set:Nx \l__siunitx_angle_minutes_tl
+          { \tl_if_blank:nF {#2} { \exp_not:n { \ensuremath {#2} } } }
+        \tl_set:Nx \l__siunitx_angle_seconds_tl
+          { \tl_if_blank:nF {#3} { \exp_not:n { \ensuremath {#3} } } }
+        \__siunitx_angle_arc_print:VVV
+          \l__siunitx_angle_degrees_tl
+          \l__siunitx_angle_minutes_tl
+          \l__siunitx_angle_seconds_tl
+      }
+  }
+\cs_new_protected:Npn \__siunitx_angle_arc_convert:n #1
+  {
+    \use:x
+      {
+        \siunitx_angle:nnn
+          { \fp_eval:n { trunc(#1,0) } }
+          { \fp_eval:n { trunc((#1 - trunc(#1,0)) * 60,0) } }
+          {
+            \fp_eval:n
+              {
+                (
+                          (#1 - trunc(#1,0)) * 60
+                  - trunc((#1 - trunc(#1,0)) * 60,0)
+                )
+                * 60
+              }
+          }
+      }
+  }
+\tl_new:N \l__siunitx_angle_degrees_tl
+\tl_new:N \l__siunitx_angle_minutes_tl
+\tl_new:N \l__siunitx_angle_seconds_tl
+\tl_new:N \l__siunitx_angle_sign_tl
+\keys_precompile:nnN
+  { siunitx }
+  {
+    input-close-uncertainty = ,
+    input-exponent-markers  = ,
+    input-open-uncertainty  = ,
+    input-uncertainty-signs =
+  }
+  \l__siunitx_angle_tmp_tl
+\cs_set_protected:Npx \__siunitx_angle_suppress_exp_uncert:
+  { \exp_not:V \l__siunitx_angle_tmp_tl }
+\keys_precompile:nnN
+  { siunitx }
+  { input-comparators = , input-signs = }
+  \l__siunitx_angle_tmp_tl
+\cs_set_protected:Npx \__siunitx_angle_suppress_comp_sign:
+  { \exp_not:V \l__siunitx_angle_tmp_tl }
+\cs_new_protected:Npn \__siunitx_angle_arc_sign:nnn #1#2#3
+  {
+    \group_begin:
+      \__siunitx_angle_suppress_exp_uncert:
+      \tl_clear:N \l__siunitx_angle_sign_tl
+      \__siunitx_angle_arc_sign:nn {#1} { degrees }
+      \__siunitx_angle_arc_sign:nn {#2} { minutes }
+      \__siunitx_angle_arc_sign:nn {#3} { seconds }
+      \tl_if_empty:NF \l__siunitx_angle_sign_tl
+        {
+          \clist_map_inline:nn { degrees , minutes , seconds }
+            {
+              \tl_if_empty:cF { l__siunitx_angle_ ##1 _tl }
+                {
+                  \tl_set:cx { l__siunitx_angle_ ##1 _tl }
+                    {
+                       { }
+                       { \exp_not:V \l__siunitx_angle_sign_tl }
+                       \exp_after:wN \exp_after:wN \exp_after:wN
+                         \__siunitx_angle_sign:nnnnnnn
+                           \cs:w l__siunitx_angle_ ##1 _tl \cs_end:
+                    }
+                  \clist_map_break:
+                }
+            }
+        }
+      \clist_map_inline:nn { degrees , minutes , seconds }
+        {
+          \tl_if_empty:cF { l__siunitx_angle_ ##1 _tl }
+            {
+              \exp_args:Ncc \siunitx_number_process:NN
+                { l__siunitx_angle_ ##1 _tl } { l__siunitx_angle_ ##1 _tl }
+              \tl_set:cx { l__siunitx_angle_ ##1 _tl }
+                {
+                  \exp_args:Nc \siunitx_number_output:NN
+                    { l__siunitx_angle_ ##1 _tl } \q_nil
+                }
+            }
+        }
+      \__siunitx_angle_arc_print:VVV
+        \l__siunitx_angle_degrees_tl
+        \l__siunitx_angle_minutes_tl
+        \l__siunitx_angle_seconds_tl
+    \group_end:
+  }
+\cs_new_protected:Npn \__siunitx_angle_arc_sign:nn #1#2
+  {
+    \tl_if_blank:nTF {#1}
+      {
+        \bool_if:cTF { l__siunitx_angle_fill_ #2 _bool }
+          {
+            \tl_set:cn { l__siunitx_angle_ #2 _tl }
+              { { } { } { 0 } { } { } { } { 0 } }
+          }
+          { \tl_clear:c { l__siunitx_angle_ #2 _tl } }
+      }
+      {
+        \siunitx_number_parse:nN {#1} \l__siunitx_angle_tmp_tl
+        \exp_after:wN \__siunitx_angle_extract_sign:nnnnnnnn \l__siunitx_angle_tmp_tl {#2}
+      }
+  }
+\cs_new_protected:Npn \__siunitx_angle_extract_sign:nnnnnnnn #1#2#3#4#5#6#7#8
+  {
+    \tl_if_blank:nTF {#2}
+      { \tl_set_eq:cN { l__siunitx_angle_ #8 _tl } \l__siunitx_angle_tmp_tl }
+      {
+        \tl_set:cn { l__siunitx_angle_ #8 _tl }
+          { {#1} { } {#3} {#4} {#5} {#6} {#7} }
+        \tl_set:Nn \l__siunitx_angle_sign_tl {#2}
+        \__siunitx_angle_suppress_comp_sign:
+      }
+  }
+\cs_new:Npn \__siunitx_angle_sign:nnnnnnn #1#2#3#4#5#6#7
+  { \exp_not:n { {#3} {#4} {#5} {#6} {#7} } }
+\box_new:N \l__siunitx_angle_marker_box
+\box_new:N \l__siunitx_angle_unit_box
+\cs_new_protected:Npn \__siunitx_angle_arc_print:nnn #1#2#3
+  {
+    \__siunitx_angle_arc_print_auxi:nVn {#1}
+      \l__siunitx_angle_symbol_degree_tl {#2#3}
+    \__siunitx_angle_arc_print_auxi:nVn {#2}
+      \l__siunitx_angle_symbol_minute_tl {#3}
+    \__siunitx_angle_arc_print_auxi:nVn {#3}
+      \l__siunitx_angle_symbol_second_tl { }
+  }
+\cs_generate_variant:Nn \__siunitx_angle_arc_print:nnn { VVV }
+\cs_new_protected:Npn \__siunitx_angle_arc_print_auxi:nnn #1#2#3
+  {
+    \tl_if_blank:nF {#1}
+      {
+        \bool_if:NTF \l_siunitx_number_parse_bool
+          {
+            \bool_if:NTF \l__siunitx_angle_astronomy_bool
+              { \__siunitx_angle_arc_print_auxii:nw {#2} #1 \q_stop }
+              {
+                \__siunitx_angle_arc_print_auxv:w #1 \q_stop
+                \__siunitx_angle_arc_print_auxvi:n {#2}
+              }
+          }
+          {
+            \siunitx_print_number:n {#1}
+            \__siunitx_angle_arc_print_auxvi:n {#2}
+          }
+       \tl_if_blank:nF {#3}
+          {
+            \nobreak
+            \l__siunitx_angle_separator_tl
+          }
+      }
+  }
+\cs_generate_variant:Nn \__siunitx_angle_arc_print_auxi:nnn { nV }
+\cs_new_protected:Npn \__siunitx_angle_arc_print_auxii:nw
+  #1#2 \q_nil #3 \q_nil #4 \q_nil #5 \q_nil #6 \q_nil #7 \q_nil #8 \q_stop
+  {
+    \mode_if_math:TF
+      { \bool_set_true:N \l__siunitx_angle_tmp_bool }
+      { \bool_set_false:N \l__siunitx_angle_tmp_bool }
+    \siunitx_print_number:n {#2#3#4}
+    \tl_if_blank:nTF {#6}
+      { \__siunitx_angle_arc_print_auxvi:n {#1} }
+      {
+        \hbox_set:Nn \l__siunitx_angle_marker_box
+          {
+            \__siunitx_angle_arc_print_auxiii:n
+               { \siunitx_print_number:n {#5} }
+          }
+        \hbox_set:Nn \l__siunitx_angle_unit_box
+          {
+            \__siunitx_angle_arc_print_auxiii:n
+              {
+                \siunitx_unit_format:nN {#1} \l__siunitx_angle_tmp_tl
+                \siunitx_print_unit:V \l__siunitx_angle_tmp_tl
+                \skip_horizontal:n { -\scriptspace }
+              }
+          }
+        \dim_compare:nNnTF { \box_wd:N \l__siunitx_angle_marker_box } >
+          { \box_wd:N \l__siunitx_angle_unit_box }
+          {
+            \__siunitx_angle_arc_print_auxiv:NN
+              \l__siunitx_angle_marker_box
+              \l__siunitx_angle_unit_box
+          }
+          {
+            \__siunitx_angle_arc_print_auxiv:NN
+              \l__siunitx_angle_unit_box
+              \l__siunitx_angle_marker_box
+          }
+        \hbox_set_to_wd:Nnn \l__siunitx_angle_marker_box
+          \l__siunitx_angle_tmp_dim
+          {
+            \hbox_overlap_right:n
+              { \box_use_drop:N \l__siunitx_angle_marker_box }
+            \hbox_overlap_right:n
+              { \box_use_drop:N \l__siunitx_angle_unit_box }
+            \tex_hfil:D
+          }
+        \box_use:N \l__siunitx_angle_marker_box
+        \skip_horizontal:N \scriptspace
+        \siunitx_print_number:n {#6}
+      }
+  }
+\cs_new_protected:Npn \__siunitx_angle_arc_print_auxiii:n #1
+  {
+    \bool_if:NTF \l__siunitx_angle_tmp_bool
+      { \ensuremath }
+      { \use:n }
+        {#1}
+  }
+\cs_new_protected:Npn \__siunitx_angle_arc_print_auxiv:NN #1#2
+  {
+    \dim_set:Nn \l__siunitx_angle_tmp_dim { \box_wd:N #1 }
+    \hbox_set_to_wd:Nnn #2
+      \l__siunitx_angle_tmp_dim
+      {
+        \tex_hss:D
+        \hbox_unpack_drop:N #2
+        \tex_hss:D
+      }
+  }
+\cs_new_protected:Npn \__siunitx_angle_arc_print_auxv:w
+  #1 \q_nil #2 \q_nil #3 \q_nil #4 \q_nil #5 \q_nil #6 \q_stop
+  { \siunitx_print_number:n {#1#2#3#4#5} }
+\cs_new_protected:Npn \__siunitx_angle_arc_print_auxvi:n #1
+  {
+    \nobreak
+    \l__siunitx_angle_product_tl
+    \siunitx_unit_format:nN {#1} \l__siunitx_angle_tmp_tl
+    \siunitx_print_unit:V \l__siunitx_angle_tmp_tl
+  }
+\keys_set:nn { siunitx }
+  {
+    angle-mode                = input      ,
+    angle-symbol-degree       = \degree    ,
+    angle-symbol-minute       = \arcminute ,
+    angle-symbol-over-decimal = false      ,
+    angle-symbol-second       = \arcsecond ,
+    angle-separator           =            ,
+    fill-angle-degrees        = false      ,
+    fill-angle-minutes        = false      ,
+    fill-angle-seconds        = false      ,
+    number-angle-product      =
+  }
+\fp_new:N \l__siunitx_complex_tmp_fp
+\tl_new:N \l__siunitx_complex_tmp_tl
+\tl_new:N \l__siunitx_complex_input_tl
+\tl_new:N \l__siunitx_complex_comparator_tl
+\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 =
+      \l__siunitx_complex_output_root_tl ,
+    print-complex-unity .bool_set:N =
+      \l__siunitx_complex_print_unity_bool
+  }
+\cs_new_protected:Npn \__siunitx_complex_parse:nNN #1#2#3
+  {
+    \group_begin:
+      \__siunitx_complex_parse_clear:
+      \protected at edef \l__siunitx_complex_arg_tl {#1}
+      \tl_set_eq:NN \l__siunitx_complex_input_tl \l__siunitx_complex_arg_tl
+      \siunitx_number_normalize_symbols:N \l__siunitx_complex_arg_tl
+      \tl_if_empty:NF \l__siunitx_complex_arg_tl
+        { \__siunitx_complex_parse_comparator: }
+      \__siunitx_complex_parse_check:
+      \cs_set_protected:Npx \__siunitx_complex_parse_end:
+        {
+          \tl_set:Nn \exp_not:N #2 { \exp_not:V \l__siunitx_complex_real_tl }
+          \tl_set:Nn \exp_not:N #3 { \exp_not:V \l__siunitx_complex_img_tl }
+        }
+    \exp_after:wN \group_end:
+    \__siunitx_complex_parse_end:
+  }
+\cs_new_protected:Npn \__siunitx_complex_parse_end: { }
+\cs_new_protected:Npn \__siunitx_complex_parse_clear:
+  {
+    \tl_clear:N \l__siunitx_complex_real_tl
+    \tl_clear:N \l__siunitx_complex_img_tl
+    \tl_clear:N \l__siunitx_complex_exp_tl
+    \tl_clear:N \l__siunitx_complex_sign_tl
+    \tl_clear:N \l__siunitx_complex_join_tl
+  }
+\cs_new_protected:Npn \__siunitx_complex_parse_check:
+  {
+    \tl_if_empty:NTF \l__siunitx_complex_img_tl
+      { \__siunitx_complex_parse_check:N \l__siunitx_complex_real_tl }
+      {
+        \tl_if_empty:NTF \l__siunitx_complex_real_tl
+          { \__siunitx_complex_parse_check:N \l__siunitx_complex_img_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_check:N \l__siunitx_complex_img_tl
+          }
+      }
+  }
+\cs_new_protected:Npn \__siunitx_complex_parse_check:N #1
+  {
+    \tl_set:Nx #1
+      {
+        \exp_not:V \l__siunitx_complex_comparator_tl
+        \exp_not:V \l__siunitx_complex_sign_tl
+        \exp_not:V #1
+        \exp_not:V \l__siunitx_complex_exp_tl
+      }
+    \tl_clear:N \l__siunitx_complex_comparator_tl
+    \tl_clear:N \l__siunitx_complex_sign_tl
+    \siunitx_number_parse:VN #1 #1
+  }
+\cs_new_protected:Npn \__siunitx_complex_parse_comparator:
+  {
+    \exp_after:wN \__siunitx_complex_parse_comparator_aux:Nw
+      \l__siunitx_complex_arg_tl \q_stop
+  }
+\cs_new_protected:Npn \__siunitx_complex_parse_comparator_aux:Nw #1#2 \q_stop
+  {
+    \tl_if_in:NnTF \l_siunitx_number_input_comparator_tl {#1}
+      {
+        \tl_set:Nn \l__siunitx_complex_comparator_tl {#1}
+        \tl_set:Nn \l__siunitx_complex_arg_tl {#2}
+      }
+      { \tl_clear:N \l__siunitx_complex_comparator_tl }
+    \tl_if_empty:NF \l__siunitx_complex_arg_tl
+      { \__siunitx_complex_parse_sign: }
+  }
+\cs_new_protected:Npn \__siunitx_complex_parse_exponent:
+  {
+    \tl_if_empty:NTF \l_siunitx_number_input_exponent_tl
+      { \__siunitx_complex_parse_root: }
+      {
+        \tl_set:Nx \l__siunitx_complex_tmp_tl
+          { \tl_head:V \l_siunitx_number_input_exponent_tl }
+        \tl_map_inline:Nn \l_siunitx_number_input_exponent_tl
+          {
+            \tl_replace_all:NnV \l__siunitx_complex_arg_tl
+              {##1} \l__siunitx_complex_tmp_tl
+          }
+        \use:x
+          {
+            \cs_set_protected:Npn
+              \exp_not:N \__siunitx_complex_parse_exponent_auxi:w
+              ####1 \exp_not:V \l__siunitx_complex_tmp_tl
+              ####2 \exp_not:V \l__siunitx_complex_tmp_tl
+              ####3 \exp_not:N \q_stop
+          }
+            { \__siunitx_complex_parse_exponent_auxii:nn {##1} {##2} }
+        \use:x
+          {
+            \__siunitx_complex_parse_exponent_auxi:w
+              \exp_not:V \l__siunitx_complex_arg_tl
+              \exp_not:V \l__siunitx_complex_tmp_tl \exp_not:N \q_nil
+              \exp_not:V \l__siunitx_complex_tmp_tl \exp_not:N \q_stop
+          }
+      }
+  }
+\cs_new_protected:Npn \__siunitx_complex_parse_exponent_auxi:w  { }
+\cs_new_protected:Npn \__siunitx_complex_parse_exponent_auxii:nn #1#2
+  {
+    \quark_if_nil:nF {#2}
+      {
+        \tl_set:Nn \l__siunitx_complex_arg_tl {#1}
+        \tl_set:Nx \l__siunitx_complex_exp_tl
+          { \exp_not:V \l__siunitx_complex_tmp_tl \exp_not:n {#2} }
+      }
+    \__siunitx_complex_parse_root:
+  }
+\cs_new_protected:Npn \__siunitx_complex_parse_root:
+  {
+    \tl_if_empty:NTF \l__siunitx_complex_input_root_tl
+      { \tl_set_eq:NN \l__siunitx_complex_real_tl \l__siunitx_complex_arg_tl }
+      {
+        \tl_set:Nx \l__siunitx_complex_tmp_tl
+          { \tl_head:V \l__siunitx_complex_input_root_tl }
+        \tl_map_inline:Nn \l__siunitx_complex_input_root_tl
+          {
+            \tl_replace_all:NnV \l__siunitx_complex_arg_tl
+              {##1} \l__siunitx_complex_tmp_tl
+          }
+        \use:x
+          {
+            \cs_set_protected:Npn
+              \exp_not:N \__siunitx_complex_parse_root_auxi:w
+              ####1 \exp_not:V \l__siunitx_complex_tmp_tl
+              ####2 \exp_not:V \l__siunitx_complex_tmp_tl
+              ####3 \exp_not:N \q_stop
+          }
+            { \__siunitx_complex_parse_root_auxii:nn {##1} {##2} }
+        \use:x
+          {
+            \__siunitx_complex_parse_root_auxi:w
+              \exp_not:V \l__siunitx_complex_arg_tl
+              \exp_not:V \l__siunitx_complex_tmp_tl \exp_not:N \q_nil
+              \exp_not:V \l__siunitx_complex_tmp_tl \exp_not:N \q_stop
+          }
+      }
+  }
+\cs_new_protected:Npn \__siunitx_complex_parse_root_auxi:w  { }
+\cs_new_protected:Npn \__siunitx_complex_parse_root_auxii:nn #1#2
+  {
+    \quark_if_nil:nTF {#2}
+      { \tl_set:Nn \l__siunitx_complex_real_tl {#1} }
+      {
+        \tl_set:Nn \l__siunitx_complex_img_tl {#2}
+        \tl_if_blank:nTF {#1}
+          {
+            \tl_if_blank:nT {#2}
+              { \tl_set:Nn \l__siunitx_complex_img_tl { 1 } }
+          }
+          {
+            \tl_if_blank:nTF {#2}
+              { \__siunitx_complex_parse_split:n {#1} }
+              { \__siunitx_complex_parse_sign_check:n {#1} }
+          }
+      }
+  }
+\cs_new_protected:Npn \__siunitx_complex_parse_sign:
+  {
+    \exp_after:wN \__siunitx_complex_parse_sign_aux:Nw
+      \l__siunitx_complex_arg_tl \q_stop
+  }
+\cs_new_protected:Npn \__siunitx_complex_parse_sign_aux:Nw #1#2 \q_stop
+  {
+    \tl_if_in:NnT \l_siunitx_number_input_sign_tl {#1}
+      {
+        \tl_set:Nn \l__siunitx_complex_sign_tl {#1}
+        \tl_set:Nn \l__siunitx_complex_arg_tl {#2}
+      }
+    \tl_if_empty:NF \l__siunitx_complex_arg_tl
+      { \__siunitx_complex_parse_exponent: }
+  }
+\cs_new_protected:Npn \__siunitx_complex_parse_sign_check:n #1
+  {
+    \__siunitx_complex_parse_sign_check:nN { } #1 \q_recursion_tail \q_recursion_stop
+  }
+\cs_new_protected:Npn \__siunitx_complex_parse_sign_check:nN #1#2
+  {
+    \quark_if_recursion_tail_stop_do:Nn #2
+      { \__siunitx_complex_parse_clear: }
+    \tl_if_in:NnTF \l_siunitx_number_input_sign_tl {#2}
+      { \__siunitx_complex_parse_sign_check:nNw {#1} #2 }
+      { \__siunitx_complex_parse_sign_check:nN {#1#2} }
+  }
+\cs_new_protected:Npn \__siunitx_complex_parse_sign_check:nNw
+  #1#2 #3 \q_recursion_tail \q_recursion_stop
+  {
+    \tl_if_blank:nTF {#3}
+      {
+        \tl_if_blank:nTF {#1}
+          { \__siunitx_complex_parse_clear: }
+          {
+            \tl_set:Nn \l__siunitx_complex_real_tl {#1}
+            \tl_set:Nn \l__siunitx_complex_join_tl {#2}
+          }
+      }
+      { \__siunitx_complex_parse_clear: }
+  }
+\cs_new_protected:Npn \__siunitx_complex_parse_split:n #1
+  {
+    \__siunitx_complex_parse_split:nN { } #1 \q_recursion_tail \q_recursion_stop
+  }
+\cs_new_protected:Npn \__siunitx_complex_parse_split:nN #1#2
+  {
+    \quark_if_recursion_tail_stop_do:Nn #2
+      { \tl_set:Nn \l__siunitx_complex_img_tl {#1} }
+    \tl_if_in:NnTF \l_siunitx_number_input_sign_tl {#2}
+      {
+        \tl_set:Nn \l__siunitx_complex_real_tl {#1}
+        \tl_set:Nn \l__siunitx_complex_join_tl {#2}
+        \__siunitx_complex_parse_split:w
+      }
+      { \__siunitx_complex_parse_split:nN {#1#2} }
+  }
+\cs_new_protected:Npn \__siunitx_complex_parse_split:w #1 \q_recursion_tail \q_recursion_stop
+  {
+    \tl_set:Nx \l__siunitx_complex_img_tl
+      {
+        \tl_if_blank:nTF {#1}
+          { 1 }
+          { \exp_not:n {#1} }
+     }
+    \tl_if_empty:NT \l__siunitx_complex_real_tl
+      { \__siunitx_complex_parse_clear: }
+  }
+\cs_new_protected:Npn \__siunitx_complex_parse_polar:nn #1#2
+  {
+    \bool_if:NTF \l_siunitx_number_parse_bool
+      { \siunitx_number_parse:nN {#1} \l__siunitx_complex_mag_tl }
+      { \tl_set:Nn \l__siunitx_complex_mag_tl { \ensuremath {#1} } }
+    \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 { ( }
+\tl_set:Nn \l__siunitx_complex_bracket_close_tl { ) }
+\tl_new:N \l__siunitx_complex_unit_tl
+\cs_new_protected:Npn \siunitx_complex_number:n #1
+  {
+    \bool_lazy_and:nnTF
+      { \l__siunitx_complex_force_polar_bool }
+      { \l_siunitx_number_parse_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_lazy_and:nnTF
+      { \l__siunitx_complex_force_cartesian_bool }
+      { \l_siunitx_number_parse_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
+  {
+    \bool_lazy_and:nnTF
+      { \l__siunitx_complex_force_polar_bool }
+      { \l_siunitx_number_parse_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_lazy_and:nnTF
+      { \l__siunitx_complex_force_cartesian_bool }
+      { \l_siunitx_number_parse_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_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_cartesian_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
+      {
+        \siunitx_number_process:NN \l__siunitx_complex_real_tl \l__siunitx_complex_real_tl
+        \tl_set:Nx \l__siunitx_complex_tmp_tl
+          { \siunitx_number_output:N \l__siunitx_complex_real_tl }
+      }
+      { \__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_cartesian_auxii: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
+    \tl_set:Nx \l__siunitx_complex_tmp_tl
+      { \siunitx_number_output:NN \l__siunitx_complex_img_tl \q_nil }
+    \exp_after:wN \__siunitx_complex_extract_exponent:w \l__siunitx_complex_tmp_tl \q_stop
+    \tl_set:Nx \l__siunitx_complex_tmp_tl
+      {
+        \bool_lazy_or:nnTF
+          {
+            \bool_lazy_and_p:nn
+              { \l_siunitx_number_bracket_ambiguous_bool }
+              { ! \tl_if_empty_p:N \l__siunitx_complex_exp_tl }
+          }
+          {
+            ! \bool_lazy_any_p:n
+              {
+                { \tl_if_blank_p:n {#1} }
+                { \tl_if_empty_p:N \l__siunitx_complex_real_tl }
+                { \tl_if_empty_p:N \l__siunitx_complex_img_tl }
+              }
+          }
+          { \__siunitx_complex_format_bracket:n }
+          { \use:n }
+          {
+            \siunitx_number_output:N \l__siunitx_complex_real_tl
+            \exp_not:V \l__siunitx_complex_sign_tl
+            \bool_if:NF \l__siunitx_complex_root_after_bool
+              { \exp_not:V \l__siunitx_complex_output_root_tl }
+             \exp_not:V \l__siunitx_complex_tmp_tl
+            \bool_if:NT \l__siunitx_complex_root_after_bool
+              { \exp_not:V \l__siunitx_complex_output_root_tl }
+           }
+         \exp_not:V \l__siunitx_complex_exp_tl
+      }
+  }
+\cs_new_protected:Npn \__siunitx_complex_drop_exponent:nnnnnnn #1#2#3#4#5#6#7
+  { \tl_set:Nn \l__siunitx_complex_real_tl { {#1} {#2} {#3} {#4} {#5} { } { 0 } } }
+\cs_new_protected:Npn \__siunitx_complex_format_sign:nnnnnnn #1#2#3#4#5#6#7
+  {
+    \tl_set:Nx \l__siunitx_complex_img_tl
+      {
+        { }
+        {
+          \tl_if_blank:nTF {#2}
+            { \tl_if_empty:NF \l__siunitx_complex_real_tl { + } }
+            { \exp_not:n {#2} }
+        }
+        \exp_not:n { {#3} {#4} {#5} {#6} {#7} }
+      }
+  }
+\cs_new_protected:Npn \__siunitx_complex_extract_exponent:w
+  #1 \q_nil #2 \q_nil #3 \q_nil #4 \q_nil #5 \q_nil #6 \q_nil #7 \q_nil #8
+  \q_nil #9 \q_stop
+  {
+    \tl_set:Nn \l__siunitx_complex_sign_tl {#1#2}
+    \bool_lazy_all:nTF
+      {
+        { ! \l__siunitx_complex_print_unity_bool }
+        { \str_if_eq_p:nn {#3} { 1 } }
+        { \tl_if_blank_p:n {#5} }
+      }
+      { \__siunitx_complex_extract_exponent_aux:nw {#6#7#8} }
+      { \__siunitx_complex_extract_exponent_aux:nw {#3#4#5#6#7#8} }
+         #9 \q_stop
+  }
+\cs_new:Npn \__siunitx_complex_extract_exponent_aux:nw
+  #1#2 \q_nil #3 \q_nil #4 \q_stop
+  {
+    \tl_set:Nn \l__siunitx_complex_tmp_tl {#1#2}
+    \tl_set:Nn \l__siunitx_complex_exp_tl {#3#4}
+  }
+\cs_new_protected:Npn \__siunitx_complex_format_bracket:n #1
+  {
+    \exp_not:V \l__siunitx_complex_bracket_open_tl
+    #1
+    \exp_not:V \l__siunitx_complex_bracket_close_tl
+  }
+\cs_new_protected:Npn \__siunitx_complex_format_cartesian_units:n #1
+  {
+    \tl_if_blank:nTF {#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
+      }
+      {
+        \use:c
+          { __siunitx_complex_format_cartesian_ \l_siunitx_quantity_prefix_mode_tl :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 }
+    \siunitx_number_process:NN \l__siunitx_complex_img_tl \l__siunitx_complex_img_tl
+    \fp_set:Nn \l__siunitx_complex_tmp_fp
+     { \exp_after:wN \__siunitx_complex_extract_exp:nnnnnnn \l__siunitx_complex_img_tl }
+    \__siunitx_complex_drop_exp:N \l__siunitx_complex_real_tl
+    \__siunitx_complex_drop_exp:N \l__siunitx_complex_img_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_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
+    \exp_not:c { __siunitx_complex_format_extract-exponent:N }
+      \exp_not:N \l__siunitx_complex_img_tl
+    \exp_not:N \tl_if_empty:NF \exp_not:N \l__siunitx_complex_real_tl
+      {
+        \exp_not:c { __siunitx_complex_format_extract-exponent:N }
+          \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: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 } } }
+\cs_new_protected:Npn \__siunitx_complex_format_polar:n #1
+  {
+    \tl_if_blank:nTF {#1}
+      {
+        \bool_if:NT \l_siunitx_number_parse_bool
+          { \siunitx_number_process:NN \l__siunitx_complex_mag_tl \l__siunitx_complex_mag_tl }
+      }
+      {
+        \bool_if:NTF \l_siunitx_number_parse_bool
+          {
+            \use:c
+              { __siunitx_complex_format_polar_ \l_siunitx_quantity_prefix_mode_tl :n } {#1}
+          }
+          { \__siunitx_complex_format_polar_input:n {#1} }
+      }
+    \tl_set:Nx \l__siunitx_complex_tmp_tl
+      {
+        \bool_if:NTF \l_siunitx_number_parse_bool
+          { \siunitx_number_output:N \l__siunitx_complex_mag_tl }
+          { \exp_not:V \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
+  {
+    \bool_if:NT \l_siunitx_number_parse_bool
+      { \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 } ,
+    print-complex-unity   = false
+  }
+\cs_generate_variant:Nn \keys_set:nn { nx }
+\cs_generate_variant:Nn \seq_use:Nnnn { NVVV }
+\fp_new:N \l__siunitx_compound_tmp_fp
+\seq_new:N \l__siunitx_compound_tmp_seq
+\tl_new:N \l__siunitx_compound_tmp_tl
+\tl_new:N \l__siunitx_compound_first_tl
+\tl_new:N \l__siunitx_compound_exp_tl
+\tl_new:N \l__siunitx_compound_start_tl
+\tl_new:N \l__siunitx_compound_end_tl
+\int_new:N \l__siunitx_compound_count_int
+\bool_new:N \l__siunitx_compound_unit_bool
+\tl_new:N \l__siunitx_compound_unit_tl
+\bool_new:N \l__siunitx_compound_boundary_text_bool
+\bool_new:N \l__siunitx_compound_exp_bracket_bool
+\bool_new:N \l__siunitx_compound_exp_combine_bool
+\bool_new:N \l__siunitx_compound_separator_text_bool
+\bool_new:N \l__siunitx_compound_unit_bracket_bool
+\bool_new:N \l__siunitx_compound_unit_power_bool
+\bool_new:N \l__siunitx_compound_unit_repeat_bool
+\keys_define:nn { siunitx }
+  {
+    compound-boundary-mode .choice: ,
+    compound-boundary-mode / number .code:n =
+      { \bool_set_false:N \l__siunitx_compound_delim_text_bool } ,
+    compound-boundary-mode / text .code:n =
+      { \bool_set_true:N \l__siunitx_compound_delim_text_bool } ,
+    compound-close-boundary .tl_set:N =
+      \l__siunitx_compound_boundary_close_tl ,
+    compound-close-bracket .tl_set:N =
+      \l__siunitx_compound_bracket_close_tl ,
+    compound-exponents .choice: ,
+    compound-exponents / combine .code:n =
+      {
+        \bool_set_false:N \l__siunitx_compound_exp_bracket_bool
+        \bool_set_true:N \l__siunitx_compound_exp_combine_bool
+      } ,
+    compound-exponents / combine-bracket .code:n =
+      {
+        \bool_set_true:N \l__siunitx_compound_exp_bracket_bool
+        \bool_set_true:N \l__siunitx_compound_exp_combine_bool
+      } ,
+    compound-exponents / individual .code:n =
+      {
+        \bool_set_false:N \l__siunitx_compound_exp_bracket_bool
+        \bool_set_false:N \l__siunitx_compound_exp_combine_bool
+      } ,
+    compound-final-separator .tl_set:N =
+      \l__siunitx_compound_separator_final_tl ,
+    compound-independent-prefix .bool_set:N =
+      \l__siunitx_compound_independent_bool ,
+    compound-pair-separator .tl_set:N =
+      \l__siunitx_compound_separator_pair_tl ,
+    compound-open-boundary .tl_set:N =
+      \l__siunitx_compound_boundary_open_tl ,
+    compound-open-bracket .tl_set:N =
+      \l__siunitx_compound_bracket_open_tl ,
+    compound-separator .tl_set:N =
+      \l__siunitx_compound_separator_tl ,
+    compound-separator-mode .choice: ,
+    compound-separator-mode / number .code:n =
+      { \bool_set_false:N \l__siunitx_compound_separator_text_bool } ,
+    compound-separator-mode / text .code:n =
+      { \bool_set_true:N \l__siunitx_compound_separator_text_bool } ,
+    compound-units .choice: ,
+    compound-units / bracket .code:n =
+      {
+        \bool_set_true:N  \l__siunitx_compound_unit_bracket_bool
+        \bool_set_false:N \l__siunitx_compound_unit_power_bool
+        \bool_set_false:N \l__siunitx_compound_unit_repeat_bool
+      } ,
+    compound-units / bracket-power .code:n =
+      {
+        \bool_set_true:N  \l__siunitx_compound_unit_bracket_bool
+        \bool_set_true:N  \l__siunitx_compound_unit_power_bool
+        \bool_set_false:N \l__siunitx_compound_unit_repeat_bool
+      } ,
+    compound-units / power .code:n =
+      {
+        \bool_set_false:N \l__siunitx_compound_unit_bracket_bool
+        \bool_set_true:N  \l__siunitx_compound_unit_power_bool
+        \bool_set_false:N \l__siunitx_compound_unit_repeat_bool
+      } ,
+    compound-units / repeat .code:n   =
+      {
+        \bool_set_false:N \l__siunitx_compound_unit_bracket_bool
+        \bool_set_false:N \l__siunitx_compound_unit_power_bool
+        \bool_set_true:N  \l__siunitx_compound_unit_repeat_bool
+      } ,
+    compound-units / single .code:n   =
+      {
+        \bool_set_false:N \l__siunitx_compound_unit_bracket_bool
+        \bool_set_false:N \l__siunitx_compound_unit_power_bool
+        \bool_set_false:N \l__siunitx_compound_unit_repeat_bool
+      }
+  }
+\cs_new_protected:Npn \siunitx_compound_number:n #1
+  {
+    \group_begin:
+      \bool_set_false:N \l__siunitx_compound_unit_bool
+      \__siunitx_compound_format:nn {#1} { }
+      \__siunitx_compound_print:N \siunitx_print_number:x
+    \group_end:
+  }
+\cs_new_protected:Npn \__siunitx_compound_format:nn #1#2
+  {
+    \seq_clear:N \l__siunitx_compound_tmp_seq
+    \bool_if:NTF \l_siunitx_number_parse_bool
+      {
+        \exp_args:Nxx \__siunitx_compound_format:nnn
+          { \tl_head:n {#1} }
+          { \tl_tail:n {#1} }
+          {#2}
+      }
+      { \tl_map_function:nN {#1} \__siunitx_compound_unparsed:n }
+  }
+\cs_new_protected:Npn \__siunitx_compound_format:nnn #1#2#3
+  {
+    \tl_if_blank:nTF {#1}
+      {
+        \tl_if_blank:nF {#2}
+          { \__siunitx_compound_format:nn {#2} {#3} }
+      }
+      { \__siunitx_compound_format_aux:nnn {#1} {#2} {#3} }
+  }
+\cs_new_protected:Npn \__siunitx_compound_format_aux:nnn #1#2#3
+  {
+    \siunitx_number_parse:nN {#1} \l__siunitx_compound_tmp_tl
+    \bool_if:NTF \l__siunitx_compound_unit_bool
+      { \__siunitx_compound_format_units:nn {#2} {#3} }
+      { \siunitx_number_process:NN \l__siunitx_compound_tmp_tl \l__siunitx_compound_first_tl }
+    \bool_lazy_and:nnTF
+      { \l__siunitx_compound_exp_combine_bool }
+      { \int_compare_p:nNn { \tl_count:n {#2} } > 0 }
+      { \__siunitx_compound_extract_exponents: }
+      {
+        \bool_if:NTF \l__siunitx_compound_unit_bool
+          {
+            \tl_set:Nx \l__siunitx_compound_tmp_tl
+              { \siunitx_number_output:NN \l__siunitx_compound_first_tl \q_nil }
+            \tl_set:Nx \l__siunitx_compound_tmp_tl
+              { \__siunitx_compound_uncert_bracket:N \l__siunitx_compound_tmp_tl }
+          }
+          {
+            \tl_set:Nx \l__siunitx_compound_tmp_tl
+              { \siunitx_number_output:N \l__siunitx_compound_first_tl }
+          }
+        \seq_put_right:NV \l__siunitx_compound_tmp_seq \l__siunitx_compound_tmp_tl
+      }
+    \tl_map_function:nN {#2} \__siunitx_compound_parsed:n
+  }
+\cs_new_protected:Npn \__siunitx_compound_extract_exponents:
+  {
+    \tl_set:Nx \l__siunitx_compound_tmp_tl
+      { \siunitx_number_output:NN \l__siunitx_compound_first_tl \q_nil }
+    \exp_after:wN \__siunitx_compound_extract_exponents_auxi:w
+      \l__siunitx_compound_tmp_tl \q_stop
+  }
+\cs_new_protected:Npn \__siunitx_compound_extract_exponents_auxi:w
+  #1 \q_nil #2 \q_nil #3 \q_nil #4 \q_nil #5 \q_nil #6 \q_nil #7 \q_nil #8
+  \q_nil #9 \q_stop
+  {
+    \__siunitx_compound_extract_exponents_auxii:nw {#1#2#3#4#5#6#7#8} #9 \q_stop
+  }
+\cs_new_protected:Npn \__siunitx_compound_extract_exponents_auxii:nw
+  #1#2 \q_nil #3 \q_nil #4 \q_stop
+  {
+    \seq_put_right:Nn \l__siunitx_compound_tmp_seq { #1#2 }
+    \tl_set:Nn \l__siunitx_compound_exp_tl { #3#4 }
+    \exp_after:wN \__siunitx_compound_extract_exponents_auxiii:nnnnnnn
+      \l__siunitx_compound_first_tl
+  }
+\cs_new_protected:Npn \__siunitx_compound_extract_exponents_auxiii:nnnnnnn
+  #1#2#3#4#5#6#7
+  {
+    \keys_set:nn { siunitx }
+      {
+        drop-exponent  = true  ,
+        exponent-mode  = fixed ,
+        fixed-exponent = #6#7
+      }
+  }
+\cs_new_protected:Npn \__siunitx_compound_parsed:n #1
+  {
+    \tl_if_blank:nF {#1}
+      { \__siunitx_compound_parsed_aux:n {#1} }
+  }
+\cs_new_protected:Npn \__siunitx_compound_parsed_aux:n #1
+  {
+    \bool_if:NTF \l__siunitx_compound_unit_bool
+      {
+        \siunitx_number_parse:nN {#1} \l__siunitx_compound_tmp_tl
+        \siunitx_number_process:NN \l__siunitx_compound_tmp_tl \l__siunitx_compound_tmp_tl
+        \tl_set:Nx \l__siunitx_compound_tmp_tl
+          { \siunitx_number_output:NN \l__siunitx_compound_tmp_tl \q_nil }
+        \tl_set:Nx \l__siunitx_compound_tmp_tl
+          { \__siunitx_compound_uncert_bracket:N \l__siunitx_compound_tmp_tl }
+      }
+      { \siunitx_number_format:nN {#1} \l__siunitx_compound_tmp_tl }
+    \seq_put_right:NV \l__siunitx_compound_tmp_seq \l__siunitx_compound_tmp_tl
+  }
+\cs_new_protected:Npn \__siunitx_compound_unparsed:n #1
+  {
+    \tl_if_blank:nF {#1}
+      { \seq_put_right:Nn \l__siunitx_compound_tmp_seq { \ensuremath {#1} } }
+  }
+\cs_new_protected:Npn \__siunitx_compound_format_units:nn #1#2
+  {
+    \bool_if:NTF \l__siunitx_compound_unit_power_bool
+      {
+        \use:c { __siunitx_compound_format_ \l_siunitx_quantity_prefix_mode_tl :nn }
+          {#2} { \tl_count:n {#1} + 1 }
+      }
+      {
+        \use:c { __siunitx_compound_format_ \l_siunitx_quantity_prefix_mode_tl :n } {#2}
+      }
+  }
+\cs_new_protected:cpx { __siunitx_compound_format_combine-exponent:n } #1
+  {
+    \exp_not:c { __siunitx_compound_format_combine-exponent_aux:n }
+      {
+        \exp_not:N \siunitx_unit_format_combine_exponent:nnN
+          {#1}
+      }
+  }
+\cs_new_protected:cpx { __siunitx_compound_format_combine-exponent:nn } #1#2
+  {
+    \exp_not:c { __siunitx_compound_format_combine-exponent_aux:n }
+      {
+        \exp_not:N \siunitx_unit_format_multiply_combine_exponent:nnnN
+          {#1} {#2}
+      }
+  }
+\cs_new_protected:cpn { __siunitx_compound_format_combine-exponent_aux:n } #1
+  {
+    \bool_set_true:N \l__siunitx_compound_exp_combine_bool
+    \siunitx_number_process:NN \l__siunitx_compound_tmp_tl \l__siunitx_compound_first_tl
+    \exp_args:NV \__siunitx_compound_extract_exp:nN
+      \l__siunitx_compound_first_tl \l__siunitx_compound_tmp_fp
+    #1 \l__siunitx_compound_tmp_fp \l__siunitx_compound_unit_tl
+  }
+\cs_new_protected:cpx { __siunitx_compound_format_extract-exponent:n } #1
+  {
+    \exp_not:c { __siunitx_compound_format_extract-exponent_aux:n }
+      { \exp_not:N \siunitx_unit_format_extract_prefixes:nNN {#1} }
+  }
+\cs_new_protected:cpx { __siunitx_compound_format_extract-exponent:nn } #1#2
+  {
+    \exp_not:c { __siunitx_compound_format_extract-exponent_aux:n }
+      {
+        \exp_not:N \siunitx_unit_format_multiply_extract_prefixes:nnNN
+          {#1} {#2}
+      }
+  }
+\cs_new_protected:cpn { __siunitx_compound_format_extract-exponent_aux:n } #1
+  {
+    #1 \l__siunitx_compound_unit_tl \l__siunitx_compound_tmp_fp
+    \tl_set:Nx \l__siunitx_compound_tmp_tl
+      { \siunitx_number_adjust_exponent:Nn \l__siunitx_compound_tmp_tl \l__siunitx_compound_tmp_fp }
+    \siunitx_number_process:NN \l__siunitx_compound_tmp_tl \l__siunitx_compound_first_tl
+    \bool_set_true:N \l__siunitx_compound_exp_combine_bool
+  }
+\cs_new_protected:Npn \__siunitx_compound_format_input:n #1
+  {
+    \siunitx_number_process:NN \l__siunitx_compound_tmp_tl \l__siunitx_compound_first_tl
+    \siunitx_unit_format:nN {#1} \l__siunitx_compound_unit_tl
+  }
+\cs_new_protected:Npn \__siunitx_compound_format_input:nn #1#2
+  {
+    \siunitx_number_process:NN \l__siunitx_compound_tmp_tl \l__siunitx_compound_first_tl
+    \siunitx_unit_format_multiply:nnN {#1} {#2} \l__siunitx_compound_unit_tl
+  }
+\cs_new_protected:Npn \__siunitx_compound_extract_exp:nN #1#2
+  { \__siunitx_compound_extract_exp:nnnnnnnN #1 #2 }
+\cs_new_protected:Npn \__siunitx_compound_extract_exp:nnnnnnnN #1#2#3#4#5#6#7#8
+  { \fp_set:Nn #8 {#6#7} }
+\cs_new_protected:Npn \siunitx_compound_quantity:nn #1#2
+  {
+    \group_begin:
+      \bool_lazy_all:nTF
+        {
+          { \l__siunitx_compound_independent_bool }
+          {
+            \str_if_eq_p:Vn
+              \l_siunitx_quantity_prefix_mode_tl
+              { combine-exponent }
+          }
+          { \int_compare_p:nNn { \tl_count:n {#1} } > 1 }
+        }
+        { \__siunitx_compound_quantity_auxi:nn }
+        { \__siunitx_compound_quantity_auxii:nn }
+          {#1} {#2}
+    \group_end:
+  }
+\cs_new_protected:Npn \__siunitx_compound_quantity_auxi:nn #1#2
+  {
+    \__siunitx_compound_print_boundary:V \l__siunitx_compound_boundary_close_tl
+    \seq_clear:N \l__siunitx_compound_tmp_seq
+    \tl_map_inline:nn {#1}
+      {
+        \seq_put_right:Nn \l__siunitx_compound_tmp_seq
+          { \siunitx_quantity:nn {##1} {#2} }
+      }
+    \seq_use:NVVV \l__siunitx_compound_tmp_seq
+      \l__siunitx_compound_separator_pair_tl
+      \l__siunitx_compound_separator_tl
+      \l__siunitx_compound_separator_final_tl
+    \__siunitx_compound_print_boundary:V \l__siunitx_compound_boundary_close_tl
+  }
+\cs_new_protected:Npn \__siunitx_compound_quantity_auxii:nn #1#2
+  {
+    \bool_if:NT \l__siunitx_compound_unit_bracket_bool
+      { \bool_set_true:N \l__siunitx_compound_exp_bracket_bool }
+    \bool_if:NT \l__siunitx_compound_unit_repeat_bool
+      { \bool_set_false:N \l__siunitx_compound_exp_combine_bool }
+    \bool_lazy_or:nnT
+      { \l__siunitx_compound_unit_bracket_bool }
+      { ! \l__siunitx_compound_unit_repeat_bool }
+      { \bool_set_false:N \l_siunitx_number_bracket_ambiguous_bool }
+    \bool_set_true:N \l__siunitx_compound_unit_bool
+    \__siunitx_compound_format:nn {#1} {#2}
+    \bool_if:NF \l_siunitx_number_parse_bool
+      { \siunitx_unit_format:nN {#2} \l__siunitx_compound_unit_tl }
+    \str_if_eq:VnT \l_siunitx_quantity_prefix_mode_tl { combine-exponent }
+      { \tl_clear:N \l__siunitx_compound_exp_tl }
+    \bool_if:NTF \l__siunitx_compound_unit_repeat_bool
+      { \__siunitx_compound_print:N \__siunitx_compound_print_quantity:x }
+      {
+        \bool_lazy_and:nnTF
+          { \l__siunitx_compound_unit_bracket_bool }
+          { \tl_if_empty_p:N \l__siunitx_compound_exp_tl }
+          {
+            \siunitx_print_number:V \l__siunitx_compound_bracket_open_tl
+            \__siunitx_compound_print:N \siunitx_print_number:x
+            \siunitx_print_number:V \l__siunitx_compound_bracket_close_tl
+          }
+          { \__siunitx_compound_print:N \siunitx_print_number:x }
+        \__siunitx_compound_print_quantity:n { \c_empty_tl }
+      }
+  }
+\cs_new_protected:Npn \__siunitx_compound_print:N #1
+  {
+    \bool_lazy_and:nnTF
+      { \l__siunitx_compound_exp_bracket_bool }
+      { ! \tl_if_empty_p:N \l__siunitx_compound_exp_tl }
+      {
+        \__siunitx_compound_print:xxN
+          { \exp_not:V \l__siunitx_compound_bracket_open_tl }
+          {
+            \exp_not:V \l__siunitx_compound_bracket_close_tl
+            \exp_not:V \l__siunitx_compound_exp_tl
+          }
+          #1
+      }
+      { \__siunitx_compound_print:xxN { } { \exp_not:V \l__siunitx_compound_exp_tl } #1 }
+  }
+\cs_new_protected:Npn \__siunitx_compound_print:nnN #1#2#3
+  {
+    \exp_args:Nx \__siunitx_compound_print:nnnN
+      { \seq_count:N \l__siunitx_compound_tmp_seq } {#1} {#2} #3
+  }
+\cs_generate_variant:Nn \__siunitx_compound_print:nnN { xx }
+\cs_new_protected:Npn \__siunitx_compound_print:nnnN #1#2#3#4
+  {
+    \int_case:nnF {#1}
+      {
+        { 0 } { }
+        { 1 }
+          {
+            #4
+              { \seq_item:Nn \l__siunitx_compound_tmp_seq { 1 } }
+          }
+        { 2 }
+          {
+            \__siunitx_compound_print_boundary:V \l__siunitx_compound_boundary_open_tl
+            #4
+              {
+                \exp_not:n {#2}
+                \seq_item:Nn \l__siunitx_compound_tmp_seq { 1 }
+              }
+            \__siunitx_compound_print_separator:V \l__siunitx_compound_separator_pair_tl
+            #4
+              {
+                \seq_item:Nn \l__siunitx_compound_tmp_seq { 2 }
+                \exp_not:n {#3}
+              }
+            \__siunitx_compound_print_boundary:V \l__siunitx_compound_boundary_open_tl
+          }
+      }
+      {
+        \int_set:Nn \l__siunitx_compound_count_int {#1}
+        \tl_set:Nn \l__siunitx_compound_start_tl {#2}
+        \tl_set:Nn \l__siunitx_compound_end_tl {#3}
+        \cs_set_eq:NN \__siunitx_compound_print_aux:n #4
+        \__siunitx_compound_print_boundary:V \l__siunitx_compound_boundary_open_tl
+        \seq_map_indexed_function:NN
+          \l__siunitx_compound_tmp_seq
+          \__siunitx_compound_print_aux:nn
+        \__siunitx_compound_print_boundary:V \l__siunitx_compound_boundary_close_tl
+      }
+  }
+\cs_new_protected:Npn \__siunitx_compound_print_aux:n #1 { }
+\cs_new_protected:Npn \__siunitx_compound_print_aux:nn #1#2
+  {
+    \int_case:nnF {#1}
+      {
+        { 1 }
+          {
+            \__siunitx_compound_print_aux:n
+              {
+                \exp_not:V \l__siunitx_compound_start_tl
+                \exp_not:n {#2}
+              }
+            \__siunitx_compound_print_separator:V \l__siunitx_compound_separator_tl
+          }
+        { \l__siunitx_compound_count_int - 1 }
+          {
+            \__siunitx_compound_print_aux:n { \exp_not:n {#2} }
+            \__siunitx_compound_print_separator:V \l__siunitx_compound_separator_final_tl
+          }
+        { \l__siunitx_compound_count_int }
+          {
+            \__siunitx_compound_print_aux:n
+              {
+                \exp_not:n {#2}
+                \exp_not:V \l__siunitx_compound_end_tl
+              }
+          }
+      }
+      {
+        \__siunitx_compound_print_aux:n { \exp_not:n {#2} }
+        \__siunitx_compound_print_separator:V \l__siunitx_compound_separator_tl
+      }
+  }
+\cs_new_protected:Npn \__siunitx_compound_print_quantity:n #1
+  { \siunitx_quantity_print:nV {#1} \l__siunitx_compound_unit_tl }
+\cs_generate_variant:Nn  \__siunitx_compound_print_quantity:n { x }
+\cs_new_protected:Npn \__siunitx_compound_print_boundary:n #1
+  {
+    \tl_if_blank:nF {#1}
+      {
+        \bool_if:NTF \l__siunitx_compound_boundary_text_bool
+          { #1 }
+          { \siunitx_print_number:n {#1} }
+      }
+  }
+\cs_generate_variant:Nn \__siunitx_compound_print_boundary:n { V }
+\cs_new_protected:Npn \__siunitx_compound_print_separator:n #1
+  {
+    \bool_if:NTF \l__siunitx_compound_separator_text_bool
+      { #1 }
+      { \siunitx_print_number:n {#1} }
+  }
+\cs_generate_variant:Nn \__siunitx_compound_print_separator:n { V }
+\cs_new:Npn \__siunitx_compound_uncert_bracket:N #1
+  { \exp_after:wN \__siunitx_compound_uncert_bracket:w #1 \q_stop }
+\cs_new:Npn \__siunitx_compound_uncert_bracket:w
+  #1 \q_nil #2 \q_nil #3 \q_nil #4 \q_nil #5 \q_nil #6 \q_nil #7 \q_nil
+  #8 \q_nil #9 \q_stop
+  { \__siunitx_compound_uncert_bracket:nnw {#1#2#3#4#5#6} {#7#8} #9 \q_stop }
+\cs_new:Npn \__siunitx_compound_uncert_bracket:nnw #1#2 #3 \q_nil #4 \q_nil #5 \q_stop
+  {
+    \bool_lazy_or:nnTF
+      { \tl_if_blank_p:n {#2#3} }
+      { ! \tl_if_blank_p:n {#5} }
+      { \exp_not:n {#1#2#3#4#5} }
+      {
+        \exp_not:V \l__siunitx_compound_bracket_open_tl
+        \exp_not:n {#1#2#3}
+        \exp_not:V \l__siunitx_compound_bracket_close_tl
+        \exp_not:n {#4#5}
+      }
+  }
+\tl_new:N \l__siunitx_list_exp_tl
+\tl_new:N \l__siunitx_list_units_tl
+\keys_define:nn { siunitx }
+  {
+    list-close-bracket .tl_set:N =
+      \l__siunitx_list_bracket_close_tl ,
+    list-exponents .choices:nn =
+      { combine , combine-bracket , individual }
+      { \tl_set_eq:NN \l__siunitx_list_exp_tl \l_keys_choice_tl } ,
+    list-final-separator .tl_set:N = \l_siunitx_list_separator_final_tl ,
+    list-independent-prefix .bool_set:N =
+      \l__siunitx_list_independent_bool ,
+    list-open-bracket .tl_set:N =
+      \l__siunitx_list_bracket_open_tl ,
+    list-pair-separator .tl_set:N = \l_siunitx_list_separator_pair_tl ,
+    list-separator .tl_set:N = \l_siunitx_list_separator_tl ,
+    list-units .choices:nn =
+      { bracket , independent , repeat , single }
+      { \tl_set_eq:NN \l__siunitx_list_units_tl \l_keys_choice_tl }
+  }
+\cs_new_protected:Npn \siunitx_number_list:nn #1
+  {
+    \group_begin:
+      \__siunitx_list_aux:
+      \siunitx_compound_number:n {#1}
+    \group_end:
+  }
+\cs_new_protected:Npn \siunitx_quantity_list:nn #1#2
+  {
+    \group_begin:
+      \__siunitx_list_aux:
+      \siunitx_compound_quantity:nn {#1} {#2}
+    \group_end:
+  }
+\cs_new_protected:Npn \__siunitx_list_aux:
+  {
+    \keys_set:nx { siunitx }
+      {
+        compound-close-bracket       =
+          { \exp_not:V \l__siunitx_list_bracket_close_tl } ,
+        compound-close-boundary       = ,
+        compound-exponents            = \l__siunitx_list_exp_tl ,
+        compound-final-separator      =
+          { \exp_not:V \l_siunitx_list_separator_final_tl } ,
+        compound-independent-prefix =
+          \bool_if:NTF \l__siunitx_list_independent_bool { true } { false } ,
+        compound-open-boundary        = ,
+        compound-open-bracket         =
+          { \exp_not:V \l__siunitx_list_bracket_open_tl } ,
+        compound-pair-separator       =
+          { \exp_not:V \l_siunitx_list_separator_pair_tl } ,
+        compound-separator            =
+          { \exp_not:V \l_siunitx_list_separator_tl } ,
+        compound-separator-mode       = text ,
+        compound-units                = \l__siunitx_list_units_tl
+      }
+  }
+\tl_new:N \l__siunitx_product_exp_tl
+\bool_new:N \l__siunitx_product_phrase_bool
+\tl_new:N \l__siunitx_product_units_tl
+\keys_define:nn { siunitx }
+  {
+    product-close-bracket .tl_set:N =
+      \l__siunitx_product_bracket_close_tl ,
+    product-exponents .choices:nn =
+      { combine , combine-bracket , individual }
+      { \tl_set_eq:NN \l__siunitx_product_exp_tl \l_keys_choice_tl } ,
+    product-independent-prefix .bool_set:N =
+      \l__siunitx_product_independent_bool ,
+    product-mode .choice: ,
+    product-mode / phrase .code:n =
+      { \bool_set_true:N \l__siunitx_product_phrase_bool } ,
+    product-mode / symbol .code:n =
+      { \bool_set_false:N \l__siunitx_product_phrase_bool } ,
+    product-open-bracket .tl_set:N =
+      \l__siunitx_product_bracket_open_tl ,
+    product-phrase .tl_set:N = \l__siunitx_product_phrase_tl ,
+    product-symbol .tl_set:N = \l__siunitx_product_symbol_tl ,
+    product-units .choices:nn =
+      { bracket , bracket-power , independent , power , repeat , single }
+      { \tl_set_eq:NN \l__siunitx_product_units_tl \l_keys_choice_tl }
+  }
+\cs_new_protected:Npn \siunitx_number_product:n #1
+  {
+    \group_begin:
+      \__siunitx_product_aux:
+      \siunitx_compound_number:n {#1}
+    \group_end:
+  }
+\cs_new_protected:Npn \siunitx_quantity_product:nn #1#2
+  {
+    \group_begin:
+      \__siunitx_product_aux:
+      \siunitx_compound_quantity:nn {#1} {#2}
+    \group_end:
+  }
+\cs_new_protected:Npn \__siunitx_product_aux:
+  {
+    \bool_if:NTF \l__siunitx_product_phrase_bool
+      { \__siunitx_product_aux:x { \exp_not:V \l__siunitx_product_phrase_tl } }
+      { \__siunitx_product_aux:x { { } \exp_not:V \l__siunitx_product_symbol_tl { } } }
+  }
+\cs_new_protected:Npn \__siunitx_product_aux:n #1
+  {
+    \keys_set:nx { siunitx }
+      {
+        compound-close-boundary       = ,
+        compound-close-bracket        =
+          { \exp_not:V \l__siunitx_product_bracket_close_tl } ,
+        compound-exponents            = \l__siunitx_product_exp_tl ,
+        compound-final-separator      = { \exp_not:n {#1} } ,
+        compound-independent-prefix =
+          \bool_if:NTF \l__siunitx_product_independent_bool { true } { false } ,
+        compound-open-boundary        = ,
+        compound-open-bracket         =
+          { \exp_not:V \l__siunitx_product_bracket_open_tl } ,
+        compound-pair-separator       = { \exp_not:n {#1} } ,
+        compound-separator            = { \exp_not:n {#1} } ,
+        compound-separator-mode       =
+          \bool_if:NTF \l__siunitx_product_phrase_bool { text } { number } ,
+        compound-units                = \l__siunitx_product_units_tl
+      }
+  }
+\cs_generate_variant:Nn \__siunitx_product_aux:n { x }
+\tl_new:N \l__siunitx_range_exp_tl
+\tl_new:N \l__siunitx_range_units_tl
+\keys_define:nn { siunitx }
+  {
+    range-close-bracket .tl_set:N =
+      \l__siunitx_range_bracket_close_tl ,
+    range-exponents .choices:nn =
+      { combine , combine-bracket , individual }
+      { \tl_set_eq:NN \l__siunitx_range_exp_tl \l_keys_choice_tl } ,
+    range-independent-prefix .bool_set:N =
+      \l__siunitx_range_independent_bool ,
+    range-open-bracket .tl_set:N =
+      \l__siunitx_range_bracket_open_tl ,
+    range-open-phrase .tl_set:N = \l__siunitx_range_open_tl ,
+    range-phrase .tl_set:N = \l_siunitx_range_phrase_tl ,
+    range-units .choices:nn =
+      { bracket , independent , repeat , single }
+      { \tl_set_eq:NN \l__siunitx_range_units_tl \l_keys_choice_tl }
+  }
+\cs_new_protected:Npn \siunitx_number_range:nn #1#2
+  {
+    \group_begin:
+      \__siunitx_range_aux:
+      \siunitx_compound_number:n { {#1} {#2} }
+    \group_end:
+  }
+\cs_new_protected:Npn \siunitx_quantity_range:nnn #1#2#3
+  {
+    \group_begin:
+      \__siunitx_range_aux:
+      \siunitx_compound_quantity:nn { {#1} {#2} } {#3}
+    \group_end:
+  }
+\cs_new_protected:Npn \__siunitx_range_aux:
+  {
+    \keys_set:nx { siunitx }
+      {
+        compound-boundary-mode        = text ,
+        compound-close-boundary       = ,
+        compound-close-bracket        =
+          { \exp_not:V \l__siunitx_range_bracket_close_tl } ,
+        compound-exponents            = \l__siunitx_range_exp_tl ,
+        compound-independent-prefix =
+          \bool_if:NTF \l__siunitx_range_independent_bool { true } { false } ,
+        compound-open-boundary        = { \exp_not:V \l__siunitx_range_open_tl } ,
+        compound-open-bracket         =
+          { \exp_not:V \l__siunitx_range_bracket_open_tl } ,
+        compound-pair-separator       =
+          { \exp_not:V \l_siunitx_range_phrase_tl } ,
+        compound-separator-mode       = text ,
+        compound-units                = \l__siunitx_range_units_tl
+      }
+  }
+\keys_set:nn { siunitx }
+  {
+    compound-boundary-mode      = text          ,
+    compound-close-boundary     =               , % (
+    compound-close-bracket      = )             ,
+    compound-exponents          = individual    ,
+    compound-final-separator    =
+      {
+        \ifmmode \  \else \space \fi
+        \text { and }
+        \ifmmode \  \else \space \fi
+      } ,
+    compound-independent-prefix = false      ,
+    compound-open-boundary      =            ,
+    compound-open-bracket       = (          , % )
+    compound-pair-separator     =
+      {
+        \ifmmode \  \else \space \fi
+        \text { and }
+        \ifmmode \  \else \space \fi
+      } ,
+    compound-separator          =
+      { , \ifmmode \  \else \space \fi } ,
+    compound-separator-mode     = text       ,
+    compound-units              = repeat     , % (
+    list-close-bracket          = )          ,
+    list-exponents              = individual ,
+    list-final-separator        =
+      {
+        \ifmmode \  \else \space \fi
+        \text { and }
+        \ifmmode \  \else \space \fi
+      } ,
+    list-independent-prefix     = false      ,
+    list-open-bracket           = (          , % )
+    list-pair-separator         =
+      {
+        \ifmmode \  \else \space \fi
+        \text { and }
+        \ifmmode \  \else \space \fi
+      } ,
+    list-separator              =
+      { , \ifmmode \  \else \space \fi } ,
+    list-units                  = repeat     , % (
+    product-close-bracket       = )          ,
+    product-exponents           = individual ,
+    product-independent-prefix  = false      ,
+    product-mode                = symbol     ,
+    product-open-bracket        = (          , % )
+    product-phrase              =
+      {
+        \ifmmode \  \else \space \fi
+        \text { by }
+        \ifmmode \  \else \space \fi
+      } ,
+    product-symbol             = \times      ,
+    product-units              = repeat      , % (
+    range-close-bracket        = )           ,
+    range-exponents            = individual  ,
+    range-independent-prefix   = false       ,
+    range-open-bracket         = (           , % )
+    range-open-phrase          =             ,
+    range-phrase               =
+      {
+        \ifmmode \  \else \space \fi
+        \text { to }
+        \ifmmode \  \else \space \fi
+      } ,
+    range-units                = repeat
+  }
+\keys_define:nn { siunitx }
+  {
+    locale .choice: ,
+    locale / DE .meta:n =
+      {
+        exponent-product      = \cdot ,
+        inter-unit-product    = \,    ,
+        output-decimal-marker = { , }
+      } ,
+    locale / FR .meta:n =
+      {
+        exponent-product      = \times ,
+        inter-unit-product    = \,     ,
+        output-decimal-marker = { , }
+      } ,
+    locale / IT .meta:n =
+      {
+        exponent-product      = \times ,
+        inter-unit-product    = \,     ,
+        output-decimal-marker = { , }
+      } ,
+    locale / PL .meta:n =
+      {
+        exponent-product      = \cdot ,
+        inter-unit-product    = \cdot ,
+        output-decimal-marker = { , }
+      } ,
+    locale / SI .meta:n =
+      {
+        exponent-product      = \times ,
+        inter-unit-product    = \,     ,
+        output-decimal-marker = { , }
+      } ,
+    locale / UK .meta:n =
+      {
+        exponent-product      = \times ,
+        inter-unit-product    = \,     ,
+        output-decimal-marker = .
+      },
+    locale / US .meta:n =
+      {
+        exponent-product      = \times ,
+        inter-unit-product    = \,     ,
+        output-decimal-marker = .
+      } ,
+    locale / ZA .meta:n =
+      {
+        exponent-product      = \times ,
+        inter-unit-product    = \cdot  ,
+        output-decimal-marker = { , }
+      }
+  }
+\file_if_exist:nT { translations.sty }
+  {
+    \RequirePackage { translations }
+    \DeclareTranslation { Catalan }    { and } { i }
+    \DeclareTranslation { Italian }    { and } { e }
+    \DeclareTranslation { Portuguese } { and } { e }
+    \DeclareTranslation { Slovene }    { and } { in }
+    \DeclareTranslation { Brazilian }  { to~(numerical~range) } { a }
+    \DeclareTranslation { Catalan }    { to~(numerical~range) } { a }
+    \DeclareTranslation { English }    { to~(numerical~range) } { to }
+    \DeclareTranslation { French }     { to~(numerical~range) } { à }
+    \DeclareTranslation { German }     { to~(numerical~range) } { bis }
+    \DeclareTranslation { Italian }    { to~(numerical~range) } { a }
+    \DeclareTranslation { Polish }     { to~(numerical~range) } { do }
+    \DeclareTranslation { Portuguese } { to~(numerical~range) } { a }
+    \DeclareTranslation { Slovene }    { to~(numerical~range) } { do }
+    \DeclareTranslation { Spanish }    { to~(numerical~range) } { a }
+    \keys_set:nn { siunitx }
+      {
+        list-final-separator =
+          {
+            \ifmmode \  \else \space \fi
+            \text { \GetTranslation { and } }
+            \ifmmode \  \else \space \fi
+          } ,
+        list-pair-separator  =
+          {
+            \ifmmode \  \else \space \fi
+            \text { \GetTranslation { and } }
+            \ifmmode \  \else \space \fi
+          } ,
+        range-phrase         =
+          {
+            \ifmmode \  \else \space \fi
+            \text { \GetTranslation { to~(numerical~range) } }
+            \ifmmode \  \else \space \fi
+          }
+      }
+  }
 \RequirePackage { amstext }
 \cs_new_eq:NN \__siunitx_print_ams_text:n \text
 \AtBeginDocument { \RequirePackage { color } }
@@ -5306,6 +5544,8 @@
         \exp_args:NV \__siunitx_table_generate_model:n \l__siunitx_table_model_tl
         \tl_set:Nn \l__siunitx_table_align_mode_tl { format }
       } ,
+    table-model-setup .tl_set:N =
+      \l__siunitx_table_model_setup_tl ,
     table-number-alignment .choices:nn =
       { center , left , right }
       { \tl_set_eq:NN \l__siunitx_table_align_number_tl \l_keys_choice_tl }
@@ -5620,7 +5860,7 @@
   #1 \q_nil #2 \q_mark #3 \q_nil #4 \q_stop
   {
     \__siunitx_table_color_check:w #3 \q_nil \q_stop
-    \__siunitx_table_print_format_box:Nn \l__siunitx_table_tmp_box {#1}
+    \__siunitx_table_print_model_box:Nn \l__siunitx_table_tmp_box {#1}
     \bool_if:NTF \l__siunitx_table_align_before_bool
       {
         \hbox_set_to_wd:Nnn \l__siunitx_table_integer_box
@@ -5644,7 +5884,7 @@
 \cs_new_protected:Npn \__siunitx_table_print_format_auxii:w
   #1 \q_nil #2 \q_nil #3 \q_mark #4 \q_nil #5 \q_nil #6 \q_stop
   {
-    \__siunitx_table_print_format_box:Nn \l__siunitx_table_tmp_box {#1#2}
+    \__siunitx_table_print_model_box:Nn \l__siunitx_table_tmp_box {#1#2}
     \dim_set:Nn \l__siunitx_table_tmp_dim { \box_wd:N \l__siunitx_table_tmp_box }
     \__siunitx_table_print_format_box:Nn \l__siunitx_table_tmp_box {#4#5}
     \dim_compare:nNnT { \box_wd:N \l__siunitx_table_tmp_box } > \l__siunitx_table_tmp_dim
@@ -5704,13 +5944,13 @@
         \__siunitx_table_fil:
         \hbox_unpack:N \l__siunitx_table_before_box
       }
-    \__siunitx_table_print_format_auxiii:w #3 \q_mark #6 \q_stop
+    \__siunitx_table_print_format_auxiii:w ? #3 \q_mark ? #6 \q_stop
   }
 \cs_new_protected:Npn \__siunitx_table_print_format_auxiii:w
   #1 \q_nil #2 \q_nil #3 \q_mark #4 \q_nil #5 \q_nil #6 \q_stop
   {
-    \__siunitx_table_print_format_box:Nn \l__siunitx_table_tmp_box {#1#2}
-    \__siunitx_table_print_format_box:Nn \l__siunitx_table_decimal_box {#4#5}
+    \__siunitx_table_print_model_box:No \l__siunitx_table_tmp_box { \use_none:n #1#2 }
+    \__siunitx_table_print_format_box:No \l__siunitx_table_decimal_box { \use_none:n #4#5 }
     \dim_set:Nn \l__siunitx_table_carry_dim
       {
           \box_wd:N \l__siunitx_table_tmp_box
@@ -5763,7 +6003,7 @@
   #1 \q_nil #2 \q_nil #3 \q_mark
   #4 \q_nil #5 \q_nil #6 \q_stop
   {
-    \__siunitx_table_print_format_box:Nn \l__siunitx_table_tmp_box {#1#2}
+    \__siunitx_table_print_model_box:Nn \l__siunitx_table_tmp_box {#1#2}
     \hbox_set_to_wd:Nnn \l__siunitx_table_tmp_box
       {
           \box_wd:N \l__siunitx_table_uncert_box
@@ -5789,7 +6029,7 @@
   #1 \q_nil #2 \q_mark
   #3 \q_nil #4 \q_stop
   {
-    \__siunitx_table_print_format_box:Nn \l__siunitx_table_tmp_box { { } #1 }
+    \__siunitx_table_print_model_box:Nn \l__siunitx_table_tmp_box { { } #1 }
     \dim_set:Nn \l__siunitx_table_tmp_dim { \box_wd:N \l__siunitx_table_tmp_box }
     \__siunitx_table_print_format_box:Nn \l__siunitx_table_tmp_box { { } #3 }
     \__siunitx_table_print_format_auxxii:w #2 \q_mark #4 \q_stop
@@ -5805,7 +6045,7 @@
   {
     \tl_if_blank:nF {#2}
       {
-        \__siunitx_table_print_format_box:Nn \l__siunitx_table_tmp_box { { } #1#2 }
+        \__siunitx_table_print_model_box:Nn \l__siunitx_table_tmp_box { { } #1#2 }
         \dim_set:Nn \l__siunitx_table_tmp_dim { \box_wd:N \l__siunitx_table_tmp_box }
         \__siunitx_table_print_format_box:Nn \l__siunitx_table_tmp_box
           {
@@ -5813,7 +6053,7 @@
               { \l__siunitx_table_align_exponent_bool }
               { \tl_if_blank_p:n {#3} }
               {
-                \__siunitx_table_print_format_box:Nn \l__siunitx_table_tmp_box { { } #1 { } }
+                \__siunitx_table_print_model_box:Nn \l__siunitx_table_tmp_box { { } #1 { } }
                 \__siunitx_table_skip:n { \box_wd:N \l__siunitx_table_tmp_box }
               }
             { } #3#4
@@ -5822,13 +6062,23 @@
       }
   }
 \cs_new_protected:Npn \__siunitx_table_print_format_box:Nn #1#2
+  { \__siunitx_table_print_format_box:nNn { } #1 {#2} }
+\cs_generate_variant:Nn \__siunitx_table_print_format_box:Nn { No }
+\cs_new_protected:Npn \__siunitx_table_print_model_box:Nn #1#2
+  { \__siunitx_table_print_format_box:VNn \l__siunitx_table_model_setup_tl #1 {#2}  }
+\cs_generate_variant:Nn \__siunitx_table_print_model_box:Nn { No }
+\cs_new_protected:Npn \__siunitx_table_print_format_box:nNn #1#2#3
   {
-    \hbox_set:Nn #1
+    \hbox_set:Nn #2
       {
-        \tl_if_blank:nF {#2}
-          { \siunitx_print_number:n {#2} }
+        \tl_if_blank:nF {#3}
+          {
+            #1
+            \siunitx_print_number:n {#3}
+          }
       }
   }
+\cs_generate_variant:Nn \__siunitx_table_print_format_box:nNn { V }
 \cs_new_protected:Npn \__siunitx_table_print_format_after:N #1
   {
     \bool_if:NTF #1
@@ -7559,6 +7809,9 @@
 \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 \T   { \tesla }
+\siunitx_declare_unit:Nn \uT  { \micro \tesla }
+\siunitx_declare_unit:Nn \mT  { \milli \tesla }
 \siunitx_declare_unit:Nn \N  {        \newton }
 \siunitx_declare_unit:Nn \mN { \milli \newton }
 \siunitx_declare_unit:Nn \kN { \kilo  \newton }
@@ -8333,12 +8586,18 @@
   }
 \keys_define:nn { siunitx }
   {
+    list-input-separator .tl_set:N =
+      \l__siunitx_list_tl ,
+    product-input-separator .tl_set:N =
+      \l__siunitx_product_tl ,
     table-column-type .tl_set:N =
       \l__siunitx_column_type_tl
   }
 \keys_set:nn { siunitx }
   {
-    table-column-type = S
+    list-input-separator    = ; ,
+    product-input-separator = x ,
+    table-column-type       = S
   }
 \msg_new:nnn { siunitx } { option-deprecated }
   {
@@ -8360,7 +8619,11 @@
   }
 \IfFormatAtLeastTF { 2020-10-01 }
   { }
-  { \RequirePackage { xparse } }
+  {
+    \RequirePackage { xparse }
+    \providecommand \ExpandArgs [1]
+      { \cs_if_exist_use:c { exp_args:N #1 } }
+  }
 \NewDocumentCommand \DeclareSIPower { +m +m m }
   {
     \siunitx_declare_power:NNn #1 #2 {#3}
@@ -8444,9 +8707,13 @@
       \siunitx_print_unit:V \l__siunitx_tmp_tl
     \group_end:
   }
-\NewDocumentCommand \qtylist
-  { O { } > { \SplitList { ; } } m > { \TrimSpaces } m }
+\ExpandArgs { Ne } \NewDocumentCommand \qtylist
   {
+    O { }
+    > { \SplitList { \exp_not:V \l__siunitx_list_tl } } m
+    > { \TrimSpaces } m
+  }
+  {
     \mode_leave_vertical:
     \group_begin:
       \siunitx_unit_options_apply:n {#3}
@@ -8454,8 +8721,12 @@
       \siunitx_quantity_list:nn {#2} {#3}
     \group_end:
   }
-\NewDocumentCommand \numlist { O { } > { \SplitList { ; } } m }
+\ExpandArgs { Ne } \NewDocumentCommand \numlist
   {
+    O { }
+    > { \SplitList { \exp_not:V \l__siunitx_list_tl } } m
+  }
+  {
     \mode_leave_vertical:
     \group_begin:
       \keys_set:nn { siunitx } {#1}
@@ -8462,9 +8733,13 @@
       \siunitx_number_list:nn {#2}
     \group_end:
   }
-\NewDocumentCommand \qtyproduct
-  { O { } > { \SplitList { x } } m > { \TrimSpaces } m }
+\ExpandArgs { Ne } \NewDocumentCommand \qtyproduct
   {
+    O { }
+    > { \SplitList { \exp_not:V \l__siunitx_product_tl } } m
+    > { \TrimSpaces } m
+  }
+  {
     \mode_leave_vertical:
     \group_begin:
       \siunitx_unit_options_apply:n {#3}
@@ -8472,9 +8747,12 @@
       \siunitx_quantity_product:nn {#2} {#3}
     \group_end:
   }
-\NewDocumentCommand \numproduct
-  { O { } > { \SplitList { x } } > { \TrimSpaces } m }
+\ExpandArgs { Ne } \NewDocumentCommand \numproduct
   {
+    O { }
+    > { \SplitList { \exp_not:V \l__siunitx_product_tl } } m
+  }
+  {
     \mode_leave_vertical:
     \group_begin:
       \keys_set:nn { siunitx } {#1}
@@ -8498,12 +8776,9 @@
       \siunitx_number_range:nn {#2} {#3}
     \group_end:
   }
-\use:e
+\ExpandArgs { Ne } \NewDocumentCommand \complexnum
+  { O { } > { \SplitArgument { 1 } { \c_colon_str } } m }
   {
-    \NewDocumentCommand \exp_not:N \complexnum
-      { O { } > { \SplitArgument { 1 } { \c_colon_str } } m }
-  }
-  {
     \mode_leave_vertical:
     \group_begin:
       \keys_set:nn { siunitx } {#1}
@@ -8510,12 +8785,9 @@
       \__siunitx_complex_number_aux:nn #2
     \group_end:
   }
-\use:e
+\ExpandArgs { Ne } \NewDocumentCommand \complexqty
+  { O { } > { \SplitArgument { 1 } { \c_colon_str } } m  m }
   {
-    \NewDocumentCommand \exp_not:N \complexqty
-      { O { } > { \SplitArgument { 1 } { \c_colon_str } } m  m }
-  }
-  {
     \mode_leave_vertical:
     \group_begin:
       \siunitx_unit_options_apply:n {#3}



More information about the tex-live-commits mailing list.