% \iffalse meta-comment
%
% File: siunitx-quantity.dtx Copyright (C) 2018-2026 Joseph Wright
%
% It may be distributed and/or modified under the conditions of the
% LaTeX Project Public License (LPPL), either version 1.3c of this
% license or (at your option) any later version.  The latest version
% of this license is in the file
%
%    https://www.latex-project.org/lppl.txt
%
% This file is part of the "siunitx bundle" (The Work in LPPL)
% and all files in that bundle must be distributed together.
%
% The released version of this bundle is available from CTAN.
%
% -----------------------------------------------------------------------
%
% The development version of the bundle can be found at
%
%    https://github.com/josephwright/siunitx
%
% for those people who are interested.
%
% -----------------------------------------------------------------------
%
%<*driver>
\documentclass{l3doc}
% Additional commands needed in this source
\ProvideDocumentCommand\email{m}{\href{mailto:#1}{\nolinkurl{#1}}}
\ProvideDocumentCommand\foreign{m}{\textit{#1}}
% The next line is needed so that \GetFileInfo will be able to pick up
% version data
\usepackage{siunitx}
\begin{document}
  \DocInput{\jobname.dtx}
\end{document}
%</driver>
% \fi
%
% \GetFileInfo{siunitx.sty}
%
% \title{^^A
%   \pkg{siunitx-quantity} -- Quantities^^A
%   \thanks{This file describes \fileversion,
%     last revised \filedate.}^^A
% }
%
% \author{^^A
%  Joseph Wright^^A
%  \thanks{^^A
%    E-mail:
%    \email{joseph@texdev.net}^^A
%   }^^A
% }
%
% \date{Released \filedate}
%
% \maketitle
%
% \begin{documentation}
%
% \section{Quantities}
%
% This submodule is focussed on providing controlled printing for quantities:
% the combination of a number and a unit. It largely builds on the submodules
% \pkg{siunitx-number} and \pkg{siunitx-unit}. A small number of adjustments
% are made to standard set up in the latter to reflect additional functionality
% added here.
%
% \begin{function}{\siunitx_quantity:nn}
%   \begin{syntax}
%     \cs{siunitx_quantity:nn} \Arg{number} \Arg{unit}
%   \end{syntax}
%   Parses the \meta{number} and the \meta{unit} as detailed for
%   \cs{siunitx_number_parse:nN} and \cs{siunitx_unit_format:nN},
%   the prints the results using \cs{siunitx_print_unit:n}.
% \end{function}
%
% \begin{function}
%   {
%     \siunitx_quantity_print:nn, \siunitx_quantity_print:nV,
%     \siunitx_quantity_print:VV, \siunitx_quantity_print:eV
%   }
%   \begin{syntax}
%     \cs{siunitx_quantity_print:nn} \Arg{number} \Arg{unit}
%   \end{syntax}
%   A low-level function which prints the quantity directly: there is
%   no processing applied to either the \meta{number} or \meta{unit}. The
%   two parts are printed using \cs{siunitx_print_unit:n} and appropriate
%   spacing and break-prevention is applied.
% \end{function}
%
% \begin{variable}{\l_siunitx_quantity_prefix_mode_str}
%   The active mode for prefix handling: one of |combine-exponent|,
%   |extract-exponent| or |input|.
% \end{variable}
%
% \begin{function}{allow-quantity-breaks}
%   \begin{syntax}
%     |allow-quantity-breaks| = |true|\verb"|"|false|
%   \end{syntax}
%   Specifies whether breaks are permitted between units. The standard setting
%   is |false|.
% \end{function}
%
% \begin{function}{prefix-mode}
%   \begin{syntax}
%     |prefix-mode| = |combine-exponent|\verb"|"|extract-exponent|\verb"|"|input|
%   \end{syntax}
%   Selects the method used for producing prefixes: a choice from the options
%   |combine-exponent|, |extract-exponent| and |input|. The option
%   |combine-exponent| combines any exponent from the number with the prefix
%   of the first unit, and prints the updated prefix. The option
%   |extract-exponent| removes all prefixes from the unit, and combines them
%   with the exponent of number. The option |input| prints prefixes and
%   exponent as given in the source. The standard setting is |input|.
% \end{function}
%
% \begin{function}{quantity-product}
%   \begin{syntax}
%     |quantity-product| = \meta{tokens}
%   \end{syntax}
%   The product marker used between a number and the unit. The standard setting
%   is~\cs{,}.
% \end{function}
%
% \begin{function}{separate-uncertainty-units}
%   \begin{syntax}
%     |separate-uncertainty-units| = |bracket|\verb"|"|repeat|\verb"|"|single|
%   \end{syntax}
%   Specifies how units are applied when a separated uncertainty is present:
%   a choice from |bracket|, |repeat| and |single|. The option |bracket| places
%   brackets around the number, with the unit given after these. The option
%   |repeat| means that the unit it printed with the main value and with the
%   uncertainty. When |single| is set, the unit is printed only once and no
%   brackets are applied. The standard setting is |bracket|.
% \end{function}
%
% \end{documentation}
%
% \begin{implementation}
%
% \section{\pkg{siunitx-quantity} implementation}
%
% Start the \pkg{DocStrip} guards.
%    \begin{macrocode}
%<*package>
%    \end{macrocode}
%
% Identify the internal prefix.
%    \begin{macrocode}
%<@@=siunitx_quantity>
%    \end{macrocode}
%
% \subsection{Initial set-up}
%
% \begin{variable}{\l_@@_tmp_fp, \l_@@_tmp_tl}
%   Scratch space.
%    \begin{macrocode}
\fp_new:N \l_@@_tmp_fp
\tl_new:N \l_@@_tmp_tl
%    \end{macrocode}
% \end{variable}
%
% \subsection{Main formatting routine}
%
% \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_siunitx_quantity_prefix_mode_str ,
%     \l_@@_break_bool                    ,
%     \l_@@_product_tl                    ,
%     \l_@@_uncert_bracket_bool           ,
%     \l_@@_uncert_repeat_bool
%   }
%    \begin{macrocode}
\str_new:N \l_siunitx_quantity_prefix_mode_str
\tl_new:N \l_siunitx_quantity_prefix_mode_tl
\bool_new:N \l_@@_uncert_bracket_bool
\bool_new:N \l_@@_uncert_repeat_bool
\keys_define:nn { siunitx }
  {
    allow-quantity-breaks .bool_set:N =
      \l_@@_break_bool ,
    prefix-mode .choices:nn =
      { combine-exponent , extract-exponent , input }
      { \str_set_eq:NN \l_siunitx_quantity_prefix_mode_str \l_keys_choice_str } ,
    quantity-product .tl_set:N =
      \l_@@_product_tl ,
    separate-uncertainty-units .choice: ,
    separate-uncertainty-units / bracket .code:n =
      {
        \bool_set_true:N \l_@@_uncert_bracket_bool
        \bool_set_false:N \l_@@_uncert_repeat_bool
      } ,
    separate-uncertainty-units / repeat .code:n =
      {
        \bool_set_false:N \l_@@_uncert_bracket_bool
        \bool_set_true:N \l_@@_uncert_repeat_bool
      } ,
    separate-uncertainty-units / single .code:n =
      {
        \bool_set_false:N \l_@@_uncert_bracket_bool
        \bool_set_false:N \l_@@_uncert_repeat_bool
      }
  }
%    \end{macrocode}
% \end{variable}
%
% \begin{variable}{\l_@@_number_tl, \l_@@_unit_tl}
%    \begin{macrocode}
\tl_new:N \l_@@_number_tl
\tl_new:N \l_@@_unit_tl
%    \end{macrocode}
% \end{variable}
%
% \begin{macro}{\siunitx_quantity:nn, \@@_parsed:nn}
% \begin{macro}
%   {
%     \@@_parsed_combine-exponent:n,
%     \@@_parsed_combine-exponent:n,
%     \@@_parsed_input:n
%   }
% \begin{macro}{\@@_parsed_aux:w}
% \begin{macro}{\@@_parsed_aux:nnnw}
% \begin{macro}{\@@_parsed_aux:nnnnw}
% \begin{macro}{\@@_parsed_aux:nnnn, \@@_parsed_aux:onnn}
% \begin{macro}{\@@_parsed_aux:nnn}
%   For quantities, there is bit to do to combine things. The first question is
%   whether we are parsing at all: if not, things are quite short. Notice that
%   within this group we turn off bracketing in the number formatter: we
%   have to deal with quantity-based brackets instead.
%    \begin{macrocode}
\cs_new_protected:Npn \siunitx_quantity:nn #1#2
  {
    \group_begin:
      \siunitx_unit_options_apply:n {#2}
      \tl_if_blank:nTF {#1}
        {
          \siunitx_unit_format:nN {#2} \l_@@_unit_tl
          \siunitx_print_unit:V \l_@@_unit_tl
        }
        {
          \bool_if:NTF \l_siunitx_number_parse_bool
            { \@@_parsed:nn {#1} {#2} }
            {
              \tl_set:Nn \l_@@_number_tl { \ensuremath {#1} }
              \siunitx_unit_format:nN {#2} \l_@@_unit_tl
              \siunitx_quantity_print:VV
                \l_@@_number_tl \l_@@_unit_tl
            }
        }
    \group_end:
  }
%    \end{macrocode}
%   For parsed numbers, we have two major questions to think about: whether we
%   are combining prefixes, and whether we have a multi-part numbers to handle.
%   Number processing has to be delayed it needs to come after any extracted
%   exponent is combined.
%    \begin{macrocode}
\cs_new_protected:Npn \@@_parsed:nn #1#2
  {
    \bool_set_false:N \l_siunitx_number_bracket_ambiguous_bool
    \siunitx_number_parse:nN {#1} \l_@@_number_tl
    \use:c { @@_parsed_ \l_siunitx_quantity_prefix_mode_str :n } {#2}
    \tl_set:Ne \l_@@_number_tl
      { \siunitx_number_output:NN \l_@@_number_tl \q_nil }
    \exp_after:wN \@@_parsed_aux:w \l_@@_number_tl \q_stop
  }
\cs_new_protected:cpn { @@_parsed_combine-exponent:n } #1
  {
    \siunitx_number_process:NN \l_@@_number_tl \l_@@_number_tl
    \@@_extract_exp:VNN
      \l_@@_number_tl \l_@@_tmp_fp \l_@@_number_tl
    \siunitx_unit_format_combine_exponent:nnN {#1}
      \l_@@_tmp_fp \l_@@_unit_tl
  }
\cs_new_protected:cpn { @@_parsed_extract-exponent:n } #1
  {
    \siunitx_unit_format_extract_prefixes:nNN {#1}
      \l_@@_unit_tl \l_@@_tmp_fp
    \tl_set:Ne \l_@@_number_tl
      {
        \siunitx_number_adjust_exponent:Nn
          \l_@@_number_tl \l_@@_tmp_fp
      }
    \siunitx_number_process:NN \l_@@_number_tl \l_@@_number_tl
  }
\cs_new_protected:Npn \@@_parsed_input:n #1
  {
    \siunitx_number_process:NN \l_@@_number_tl \l_@@_number_tl
    \siunitx_unit_format:nN {#1} \l_@@_unit_tl
  }
%    \end{macrocode}
%   To find out if we need to work harder, we first need to split the formatted
%   number into the constituent parts. That is done using the table-like
%   approach: that avoids needing to both check the settings and break down
%   the input separately.
%    \begin{macrocode}
\cs_new_protected:Npn \@@_parsed_aux: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
  { \@@_parsed_aux:nnnw {#1} {#2#3#4#5} {#6#7#8} #9 \q_stop }
\cs_new_protected:Npn \@@_parsed_aux:nnnw #1#2#3 #4 \q_nil
  { \@@_parsed_aux:nnnnw {#1} {#2} {#3} {#4} ? }
\cs_new_protected:Npn \@@_parsed_aux:nnnnw
  #1#2#3#4 #5 \q_nil #6 \q_stop
  { \@@_parsed_aux:onnn { \use_none:n #5#6 } {#1} {#2} {#3#4} }
\cs_new_protected:Npn \@@_parsed_aux:nnnn #1#2#3#4
  {
    \tl_if_blank:nTF {#4}
      { \siunitx_quantity_print:nV {#2#3#1} \l_@@_unit_tl }
      {
        \bool_if:NTF \l_@@_uncert_bracket_bool
          {
            \siunitx_quantity_print:eV
              {
                \exp_not:n {#2}
                \exp_not:V \l_@@_bracket_open_tl
                \exp_not:n {#3#4}
                \exp_not:V \l_@@_bracket_close_tl
                \exp_not:n {#1}
              }
            \l_@@_unit_tl
          }
          {
            \bool_if:NTF \l_@@_uncert_repeat_bool
              {
                \tl_if_blank:nTF {#1}
                  { \@@_parsed_aux:nnn {#2#3} {#4} { } }
                  { \@@_parsed_aux:nnn {#2#3} {#4} { { } #1 } }
              }
              { \siunitx_quantity_print:nV {#2#3#4#1} \l_@@_unit_tl }
          }
      }
  }
\cs_generate_variant:Nn \@@_parsed_aux:nnnn { o }
%    \end{macrocode}
%   For the case of a separated uncertainty with repeated units, we print the
%   two parts independently. The third argument here is the exponent if there
%   is one, with the spacing correct in either case as we only pass the empty
%   group if one is required.
%    \begin{macrocode}
\cs_new_protected:Npn \@@_parsed_aux:nnn #1#2#3
  {
    \siunitx_quantity_print:nV {#1#3} \l_@@_unit_tl
    \tl_if_blank:nF {#2}
      { \siunitx_quantity_print:nV { { } #2#3 } \l_@@_unit_tl }
  }
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\@@_extract_exp:nNN, \@@_extract_exp:VNN}
% \begin{macro}{\@@_extract_exp:nnnnnnnNN}
%   To extract the exponent part for a combined prefix, we decompose the value
%   and remove it. As the exponent part may be entirely empty, we add a filler
%   zero.
%    \begin{macrocode}
\cs_new_protected:Npn \@@_extract_exp:nNN #1#2#3
  { \@@_extract_exp:nnnnnnnNN #1 #2 #3 }
\cs_generate_variant:Nn \@@_extract_exp:nNN { V }
\cs_new_protected:Npn \@@_extract_exp:nnnnnnnNN #1#2#3#4#5#6#7#8#9
  {
    \fp_set:Nn #8 { #6 0#7 }
    \tl_set:Ne #9
      { {#1} {#2} {#3} {#4} {#5} { } { } }
  }
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}
%   {
%     \siunitx_quantity_print:nn, \siunitx_quantity_print:nV,
%     \siunitx_quantity_print:VV, \siunitx_quantity_print:eV
%   }
% \begin{macro}{\@@_print_unit:n}
% \begin{macro}{\@@_print_mathchoice:Nnnnn}
% \begin{macro}{\@@_print_mathchoice:nnN}
%   For printing a single part of a quantity. This is needed for compound
%   quantities and so is public: that's also the reason for passing both
%   argument explicitly. The semantics here require that the penalty and
%   spacing are always applied: the number argument may be empty. The lazy test
%   here is looking for the case where a |1| has been inserted at the start of
%   a format unit \emph{and} we have some other number to print: the |1| is
%   then removed and there is no space inserted.
%    \begin{macrocode}
\cs_new_protected:Npn \siunitx_quantity_print:nn #1#2
  {
    \siunitx_print_number:n {#1}
    \tl_if_blank:nF {#2}
      {
        \tl_if_blank:nTF {#1}
          { \@@_print_unit:n {#2} }
          {
            \tl_if_head_eq_charcode:nNTF {#2} 1
              { \siunitx_print_unit:o { \use_none:n #2 } }
              {
                \tl_if_head_eq_meaning:nNTF {#2} \mathchoice
                  { \@@_print_mathchoice:Nnnnn #2 }
                  { \@@_print_unit:n {#2} }
              }
          }
      }
  }
\cs_generate_variant:Nn \siunitx_quantity_print:nn { nV , VV , eV , xV }
\cs_new_protected:Npn \@@_print_unit:n #1
  {
    \bool_if:NTF \l_@@_break_bool
      { \penalty \binoppenalty }
      { \nobreak }
    \tl_use:N \l_@@_product_tl
    \siunitx_print_unit:n {#1}
  }
%    \end{macrocode}
%  If the first token of the unit is |\mathchoice|, we are looking at
%  formatting differently in display and inline math modes. If we then have a
%  leading |1|, then it needs to be lopped off. We also need to remember here
%  that the spacing also needs to be inside the |\mathchoice|, as it only
%  applies in display mode. To get all of this to work, there is then some
%  nesting of print functions: unavoidable. As |#3|, |#4| and |#5| are
%  identical, expansion can take place just once to pass the trimmed tokens.
%    \begin{macrocode}
\cs_new_protected:Npn \@@_print_mathchoice:Nnnnn #1#2#3#4#5
  {
    \tl_if_head_eq_charcode:nNTF {#3} 1
      {
        \exp_args:No \@@_print_mathchoice:nnN
          { \use_none:n #3 } {#2} #1
      }
      { \@@_print_unit:n { #1 {#2} {#3} {#4} {#5} } }
  }
\cs_new_protected:Npn \@@_print_mathchoice:nnN #1#2#3
  {
    \siunitx_print_unit:n
      { #3 { \@@_print_unit:n {#2} } {#1} {#1} {#1} }
  }
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \subsection{Standard settings for module options}
%
% Some of these follow naturally from the point of definition
% (\foreign{e.g.}~boolean variables are always |false| to begin with),
% but for clarity everything is set here.
%    \begin{macrocode}
\keys_set:nn { siunitx }
  {
    allow-quantity-breaks      = false  ,
    prefix-mode                = input ,
    quantity-product           = \,     ,
    separate-uncertainty-units = bracket
  }
%    \end{macrocode}
%
% \subsection{Adjustments to units}
%
% \begin{macro}{\arcminute, \arcsecond, \degree}
%   The angles units are adjusted here: this is needed for using it
%   in quantities. This is done here as it avoids a dependency in
%   \pkg{siunitx-unit} on options it does not contain.
%    \begin{macrocode}
\siunitx_unit_options_declare:Nn \arcminute
  { prefix-mode = input , quantity-product = { } }
\siunitx_unit_options_declare:Nn \arcsecond
  { prefix-mode = input , quantity-product = { } }
\siunitx_unit_options_declare:Nn \degree
  { prefix-mode = input , quantity-product = { } }
\siunitx_unit_options_declare:Nn \percent
  { prefix-mode = input }
%    \end{macrocode}
% \end{macro}
%
%    \begin{macrocode}
%</package>
%    \end{macrocode}
%
% \end{implementation}
%
% \PrintIndex
