summaryrefslogtreecommitdiff
path: root/macros/latex/contrib/siunitx/siunitx-complex.dtx
diff options
context:
space:
mode:
Diffstat (limited to 'macros/latex/contrib/siunitx/siunitx-complex.dtx')
-rw-r--r--macros/latex/contrib/siunitx/siunitx-complex.dtx849
1 files changed, 849 insertions, 0 deletions
diff --git a/macros/latex/contrib/siunitx/siunitx-complex.dtx b/macros/latex/contrib/siunitx/siunitx-complex.dtx
new file mode 100644
index 0000000000..87c1b684ef
--- /dev/null
+++ b/macros/latex/contrib/siunitx/siunitx-complex.dtx
@@ -0,0 +1,849 @@
+% \iffalse meta-comment
+%
+% File: siunitx-complex.dtx Copyright (C) 2021 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}
+\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-complex} -- Complex numbers^^A
+% \thanks{This file describes \fileversion,
+% last revised \filedate.}^^A
+% }
+%
+% \author{^^A
+% Joseph Wright^^A
+% \thanks{^^A
+% E-mail:
+% \href{mailto:joseph.wright@morningstar2.co.uk}
+% {joseph.wright@morningstar2.co.uk}^^A
+% }^^A
+% }
+%
+% \date{Released \filedate}
+%
+% \maketitle
+%
+% \begin{documentation}
+%
+% This submodule is concerned with formatting complex numbers. It augments the
+% standard functions \cs{siunitx_number_format:nN} and \cs{siunitx_quantity:nn}
+% by allowing parsing of numbers with a complex part. There are no additional
+% assumptions concerning \LaTeXe{} commands in the submodule beyond those in the
+% core number and unit submodules.
+%
+% \begin{function}{\siunitx_complex_number:n}
+% \begin{syntax}
+% \cs{siunitx_complex_number:n} \Arg{number}
+% \end{syntax}
+% Parses the \meta{number} and splits into real and complex parts, which are
+% then formatted as described for \cs{siunitx_number_format:nN}. The results
+% are combined and printed using the standard functions in the module.
+% \end{function}
+%
+% \begin{function}{\siunitx_complex_quantity:nn}
+% \begin{syntax}
+% \cs{siunitx_complex_quantity:n} \Arg{number} \Arg{units}
+% \end{syntax}
+% Parses the \meta{number} and splits into real and complex parts, which are
+% then formatted as described for \cs{siunitx_quantity:nn}. The results
+% are combined and printed using the standard functions in the module.
+% \end{function}
+%
+% \begin{function}{complex-root-position}
+% \begin{syntax}
+% |complex-root-position| = |after-number|\verb"|"|before-number|
+% \end{syntax}
+% Choice which determines where the complex root symbol is printed relative
+% to the numbers. The standard setting is |after-number|.
+% \end{function}
+%
+% \begin{function}{input-complex-root}
+% \begin{syntax}
+% |input-complex-root| = \meta{tokens}
+% \end{syntax}
+% The token(s) considered as complexes roots for number parsing.
+% The standard setting is |ij|.
+% \end{function}
+%
+% \begin{function}{output-complex-root}
+% \begin{syntax}
+% |output-complex-root| = \meta{tokens}
+% \end{syntax}
+% The token(s) used to show the complex root in output. The standard setting
+% is |\mathrm{i}|.
+% \end{function}
+%
+% \end{documentation}
+%
+% \begin{implementation}
+%
+% Start the \pkg{DocStrip} guards.
+% \begin{macrocode}
+%<*package>
+% \end{macrocode}
+%
+% \section{\pkg{siunitx-complex} implementation}
+%
+% Identify the internal prefix (\LaTeX3 \pkg{DocStrip} convention): only
+% internal material in this \emph{submodule} should be used directly.
+% \begin{macrocode}
+%<@@=siunitx_complex>
+% \end{macrocode}
+%
+% \subsection{General setup}
+%
+% \begin{variable}{\l_@@_tmp_tl}
+% \begin{macrocode}
+\tl_new:N \l_@@_tmp_tl
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\l_@@_input_tl}
+% The numerical input exactly as given by the user.
+% \begin{macrocode}
+\tl_new:N \l_@@_input_tl
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\l_@@_comparator_tl}
+% A comparator, if found, is held here.
+% \begin{macrocode}
+\tl_new:N \l_@@_comparator_tl
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\l_@@_exp_tl}
+% The exponent part of a parsed number.
+% \begin{macrocode}
+\tl_new:N \l_@@_exp_tl
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\l_@@_real_tl, \l_@@_img_tl}
+% The real and imaginary parts of the number, respectively.
+% \begin{macrocode}
+\tl_new:N \l_@@_real_tl
+\tl_new:N \l_@@_img_tl
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\l_@@_join_tl, \l_@@_sign_tl}
+% Staging posts for a joining and leading sign, respectively.
+% \begin{macrocode}
+\tl_new:N \l_@@_join_tl
+\tl_new:N \l_@@_sign_tl
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\l_@@_input_root_tl, \l_@@_output_root_tl}
+% \begin{macrocode}
+\bool_new:N \l_@@_root_after_bool
+\keys_define:nn { siunitx }
+ {
+ complex-root-position .choice: ,
+ complex-root-position / after-number .code:n =
+ { \bool_set_true:N \l_@@_root_after_bool } ,
+ complex-root-position / before-number .code:n =
+ { \bool_set_false:N \l_@@_root_after_bool } ,
+ input-complex-root .tl_set:N =
+ \l_@@_input_root_tl ,
+ output-complex-root .tl_set:N =
+ \l_@@_output_root_tl
+ }
+% \end{macrocode}
+% \end{variable}
+%
+% \subsection{Parsing}
+%
+% \begin{macro}{\@@_parse:nNN}
+% \begin{macro}{\@@_parse_end:}
+% \begin{macro}{\@@_parse_clear:}
+% Parsing for complex numbers needs some of the same approaches as the
+% general parser. However, as the aim here is to do only enough to split
+% the real and imaginary parts before handing off the the usual code,
+% it's not a full repeat. Instead, we shortcut where we can. The |clear|
+% function here is not only there to make this function shorter: it
+% also allows a single way to zap any stored data if a parse error occurs.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_parse:nNN #1#2#3
+ {
+ \group_begin:
+ \@@_parse_clear:
+ \protected@edef \l_@@_arg_tl {#1}
+ \tl_set_eq:NN \l_@@_input_tl \l_@@_arg_tl
+ \siunitx_number_normalize_symbols:N \l_@@_arg_tl
+ \tl_if_empty:NF \l_@@_arg_tl
+ { \@@_parse_comparator: }
+ \@@_parse_check:
+ \cs_set_protected:Npx \@@_parse_end:
+ {
+ \tl_set:Nn \exp_not:N #2 { \exp_not:V \l_@@_real_tl }
+ \tl_set:Nn \exp_not:N #3 { \exp_not:V \l_@@_img_tl }
+ }
+ \exp_after:wN \group_end:
+ \@@_parse_end:
+ }
+\cs_new_protected:Npn \@@_parse_end: { }
+\cs_new_protected:Npn \@@_parse_clear:
+ {
+ \tl_clear:N \l_@@_real_tl
+ \tl_clear:N \l_@@_img_tl
+ \tl_clear:N \l_@@_exp_tl
+ \tl_clear:N \l_@@_sign_tl
+ \tl_clear:N \l_@@_join_tl
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\@@_parse_check:, \@@_parse_finalise:}
+% \begin{macro}{\@@_parse_finalise:N}
+% Now we tidy up and do the main work: passing to the standard formatter for
+% final parsing.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_parse_check:
+ {
+ \bool_lazy_all:nTF
+ {
+ { \tl_if_empty_p:N \l_@@_real_tl }
+ { \tl_if_empty_p:N \l_@@_img_tl }
+ { \tl_if_empty_p:N \l_@@_exp_tl }
+ }
+ {
+ \msg_error:nnx { siunitx } { invalid-complex-number }
+ { \exp_not:V \l_@@_input_tl }
+ }
+ { \@@_parse_finalise: }
+ }
+\cs_new_protected:Npn \@@_parse_finalise:
+ {
+ \tl_if_empty:NTF \l_@@_img_tl
+ { \@@_parse_finalise:N \l_@@_real_tl }
+ {
+ \tl_if_empty:NTF \l_@@_real_tl
+ { \@@_parse_finalise:N \l_@@_img_tl }
+ {
+ \@@_parse_finalise:N \l_@@_real_tl
+ \tl_set_eq:NN \l_@@_sign_tl \l_@@_join_tl
+ \@@_parse_finalise:N \l_@@_img_tl
+ }
+ }
+ }
+\cs_new_protected:Npn \@@_parse_finalise:N #1
+ {
+ \tl_set:Nx #1
+ {
+ \exp_not:V \l_@@_comparator_tl
+ \exp_not:V \l_@@_sign_tl
+ \exp_not:V #1
+ \exp_not:V \l_@@_exp_tl
+ }
+ \tl_clear:N \l_@@_comparator_tl
+ \tl_clear:N \l_@@_sign_tl
+ \siunitx_number_parse:VN #1 #1
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\@@_parse_comparator:}
+% \begin{macro}{\@@_parse_comparator_aux:Nw}
+% The first step is to extract any comparator: this is the same as
+% for a full number parse.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_parse_comparator:
+ {
+ \exp_after:wN \@@_parse_comparator_aux:Nw
+ \l_@@_arg_tl \q_stop
+ }
+\cs_new_protected:Npn \@@_parse_comparator_aux:Nw #1#2 \q_stop
+ {
+ \tl_if_in:NnTF \l_siunitx_number_input_comparator_tl {#1}
+ {
+ \tl_set:Nn \l_@@_comparator_tl {#1}
+ \tl_set:Nn \l_@@_arg_tl {#2}
+ }
+ { \tl_clear:N \l_@@_comparator_tl }
+ \tl_if_empty:NF \l_@@_arg_tl
+ { \@@_parse_sign: }
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\@@_parse_exponent:}
+% \begin{macro}{\@@_parse_exponent_auxi:w}
+% \begin{macro}{\@@_parse_exponent_auxii:nn}
+% An exponent part of a number has to come at the end and can only occur
+% once. Thus it is relatively easy to parse. The code here is a simplified
+% version of that in \pkg{siunitx-number}: we only need to find \emph{some}
+% exponent, not check on the detail. Notice that we need to retain the
+% exponent marker here: that is done using the short-lived temporary
+% variable.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_parse_exponent:
+ {
+ \tl_if_empty:NTF \l_siunitx_number_input_exponent_tl
+ { \@@_parse_root: }
+ {
+ \tl_set:Nx \l_@@_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_@@_arg_tl
+ {##1} \l_@@_tmp_tl
+ }
+ \use:x
+ {
+ \cs_set_protected:Npn
+ \exp_not:N \@@_parse_exponent_auxi:w
+ ####1 \exp_not:V \l_@@_tmp_tl
+ ####2 \exp_not:V \l_@@_tmp_tl
+ ####3 \exp_not:N \q_stop
+ }
+ { \@@_parse_exponent_auxii:nn {##1} {##2} }
+ \use:x
+ {
+ \@@_parse_exponent_auxi:w
+ \exp_not:V \l_@@_arg_tl
+ \exp_not:V \l_@@_tmp_tl \exp_not:N \q_nil
+ \exp_not:V \l_@@_tmp_tl \exp_not:N \q_stop
+ }
+ }
+ }
+\cs_new_protected:Npn \@@_parse_exponent_auxi:w { }
+\cs_new_protected:Npn \@@_parse_exponent_auxii:nn #1#2
+ {
+ \quark_if_nil:nF {#2}
+ {
+ \tl_set:Nn \l_@@_arg_tl {#1}
+ \tl_set:Nx \l_@@_exp_tl
+ { \exp_not:V \l_@@_tmp_tl \exp_not:n {#2} }
+ }
+ \@@_parse_root:
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\@@_parse_root:}
+% \begin{macro}{\@@_parse_root_auxi:w}
+% \begin{macro}{\@@_parse_root_auxii:nn}
+% Splitting at the complex root is much like splitting the exponent.
+% After dealing with the case where there is no complex root allowed,
+% use the first possible symbol to do the work.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_parse_root:
+ {
+ \tl_if_empty:NTF \l_@@_input_root_tl
+ { \tl_set_eq:NN \l_@@_real_tl \l_@@_arg_tl }
+ {
+ \tl_set:Nx \l_@@_tmp_tl
+ { \tl_head:V \l_@@_input_root_tl }
+ \tl_map_inline:Nn \l_@@_input_root_tl
+ {
+ \tl_replace_all:NnV \l_@@_arg_tl
+ {##1} \l_@@_tmp_tl
+ }
+ \use:x
+ {
+ \cs_set_protected:Npn
+ \exp_not:N \@@_parse_root_auxi:w
+ ####1 \exp_not:V \l_@@_tmp_tl
+ ####2 \exp_not:V \l_@@_tmp_tl
+ ####3 \exp_not:N \q_stop
+ }
+ { \@@_parse_root_auxii:nn {##1} {##2} }
+ \use:x
+ {
+ \@@_parse_root_auxi:w
+ \exp_not:V \l_@@_arg_tl
+ \exp_not:V \l_@@_tmp_tl \exp_not:N \q_nil
+ \exp_not:V \l_@@_tmp_tl \exp_not:N \q_stop
+ }
+ }
+ }
+\cs_new_protected:Npn \@@_parse_root_auxi:w { }
+% \end{macrocode}
+% This is where the business end lies. We have four possibilities:
+% \begin{itemize}
+% \item There was no complex root at all: |#2| will be |\q_nil|
+% \item All of the number is in the complex part with a leading
+% root: |#1| will be empty. This includes the case where
+% the input was \emph{just} a root symbol (plus possibly sign,
+% exponent): we need to cover that.
+% \item All of the number was before the complex root: |#2| will
+% be empty and we need to check |#1| fully to split out the two
+% parts
+% \item The input has a a real part with the complex part starting
+% with the root symbol: just the last token needs to be separated.
+% \end{itemize}
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_parse_root_auxii:nn #1#2
+ {
+ \quark_if_nil:nTF {#2}
+ { \tl_set:Nn \l_@@_real_tl {#1} }
+ {
+ \tl_set:Nn \l_@@_img_tl {#2}
+ \tl_if_blank:nTF {#1}
+ {
+ \tl_if_blank:nT {#2}
+ { \tl_set:Nn \l_@@_img_tl { 1 } }
+ }
+ {
+ \tl_if_blank:nTF {#2}
+ { \@@_parse_split:n {#1} }
+ { \@@_parse_sign_check:n {#1} }
+ }
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\@@_parse_sign:}
+% \begin{macro}{\@@_parse_sign_aux:Nw}
+% The first token of a number after a comparator could be a sign. A quick
+% check is made and if found stored. There is no need to worry about the
+% nature of the sign: we keep them regardless.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_parse_sign:
+ {
+ \exp_after:wN \@@_parse_sign_aux:Nw
+ \l_@@_arg_tl \q_stop
+ }
+\cs_new_protected:Npn \@@_parse_sign_aux:Nw #1#2 \q_stop
+ {
+ \tl_if_in:NnT \l_siunitx_number_input_sign_tl {#1}
+ {
+ \tl_set:Nn \l_@@_sign_tl {#1}
+ \tl_set:Nn \l_@@_arg_tl {#2}
+ }
+ \tl_if_empty:NF \l_@@_arg_tl
+ { \@@_parse_exponent: }
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\@@_parse_sign_check:n}
+% \begin{macro}{\@@_parse_sign_check:nN}
+% \begin{macro}{\@@_parse_sign_check:nNw}
+% Here, we want to check that the last token in the input is a sign.
+% There cannot be anything after the sign, and there has to be at one
+% token before the sign: we can therefore signal a parsing error if we
+% need to.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_parse_sign_check:n #1
+ {
+ \@@_parse_sign_check:nN { } #1 \q_recursion_tail \q_recursion_stop
+ }
+\cs_new_protected:Npn \@@_parse_sign_check:nN #1#2
+ {
+ \quark_if_recursion_tail_stop_do:Nn #2
+ { \@@_parse_clear: }
+ \tl_if_in:NnTF \l_siunitx_number_input_sign_tl {#2}
+ { \@@_parse_sign_check:nNw {#1} #2 }
+ { \@@_parse_sign_check:nN {#1#2} }
+ }
+\cs_new_protected:Npn \@@_parse_sign_check:nNw
+ #1#2 #3 \q_recursion_tail \q_recursion_stop
+ {
+ \tl_if_blank:nTF {#3}
+ {
+ \tl_if_blank:nTF {#1}
+ { \@@_parse_clear: }
+ {
+ \tl_set:Nn \l_@@_real_tl {#1}
+ \tl_set:Nn \l_@@_join_tl {#2}
+ }
+ }
+ { \@@_parse_clear: }
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\@@_parse_split:n}
+% \begin{macro}{\@@_parse_split:nN}
+% \begin{macro}{\@@_parse_split:w}
+% Checking for a sign inside the leading part of the number is a simple loop.
+% There is the possibility that there is no number in the imaginary part
+% needs to be allowed for. Notice that we do a check that there is some
+% real part: this covers for example an original input |++1i|, which
+% otherwise would not be trapped.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_parse_split:n #1
+ {
+ \@@_parse_split:nN { } #1 \q_recursion_tail \q_recursion_stop
+ }
+\cs_new_protected:Npn \@@_parse_split:nN #1#2
+ {
+ \quark_if_recursion_tail_stop_do:Nn #2
+ { \tl_set:Nn \l_@@_img_tl {#1} }
+ \tl_if_in:NnTF \l_siunitx_number_input_sign_tl {#2}
+ {
+ \tl_set:Nn \l_@@_real_tl {#1}
+ \tl_set:Nn \l_@@_join_tl {#2}
+ \@@_parse_split:w
+ }
+ { \@@_parse_split:nN {#1#2} }
+ }
+\cs_new_protected:Npn \@@_parse_split:w #1 \q_recursion_tail \q_recursion_stop
+ {
+ \tl_set:Nx \l_@@_img_tl
+ {
+ \tl_if_blank:nTF {#1}
+ { 1 }
+ { \exp_not:n {#1} }
+ }
+ \tl_if_empty:NT \l_@@_real_tl
+ { \@@_parse_clear: }
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \section{Formatting}
+%
+% \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_@@_unit_tl}
+% \begin{macrocode}
+\tl_new:N \l_@@_unit_tl
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{macro}{\siunitx_complex_number:n}
+% \begin{macro}{\siunitx_complex_quantity:nn}
+% The work here is pretty trivial.
+% \begin{macrocode}
+\cs_new_protected:Npn \siunitx_complex_number:n #1
+ {
+ \group_begin:
+ \bool_if:NTF \l_siunitx_number_parse_bool
+ {
+ \@@_parse:nNN {#1} \l_@@_real_tl \l_@@_img_tl
+ \@@_format:n { }
+ }
+ {
+ \siunitx_number_format:nN {#1} \l_@@_tmp_tl
+ \siunitx_print_number:V \l_@@_tmp_tl
+ }
+ \group_end:
+ }
+\cs_new_protected:Npn \siunitx_complex_quantity:nn #1#2
+ {
+ \group_begin:
+ \bool_if:NTF \l_siunitx_number_parse_bool
+ {
+ \@@_parse:nNN {#1} \l_@@_real_tl \l_@@_img_tl
+ \@@_format:n {#2}
+ }
+ { \siunitx_quantity:nn {#1} {#2} }
+ \group_end:
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\@@_format:n}
+% \begin{macro}{\@@_format_auxi:n}
+% \begin{macro}{\@@_format_unary:nnnnnnn}
+% \begin{macro}{\@@_format_auxii:n}
+% \begin{macro}{\@@_drop_exponent:nnnnnnn}
+% \begin{macro}{\@@_format_sign:nnnnnnn}
+% \begin{macro}{\@@_extract_exponent:nw}
+% \begin{macro}{\@@_extract_exponent_aux:w}
+% \begin{macro}[EXP]{\@@_format_bracket:n}
+% We start here checking that there is something to do.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_format:n #1
+ {
+ \bool_lazy_and:nnF
+ { \tl_if_empty_p:N \l_@@_real_tl }
+ { \tl_if_empty_p:N \l_@@_img_tl }
+ { \@@_format_auxi:n {#1} }
+ }
+% \end{macrocode}
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_format_auxi:n #1
+ {
+ \tl_clear:N \l_@@_tmp_tl
+ \tl_if_empty:NTF \l_@@_real_tl
+ {
+ \@@_format_units:n {#1}
+ \exp_after:wN \@@_format_unary:nnnnnnn \l_@@_img_tl
+ \tl_set:Nx \l_@@_tmp_tl
+ {
+ \siunitx_number_output:N \l_@@_img_tl
+ \exp_not:V \l_@@_output_root_tl
+ }
+ }
+ {
+ \tl_if_empty:NTF \l_@@_img_tl
+ {
+ \siunitx_number_process:NN \l_@@_real_tl \l_@@_real_tl
+ \tl_set:Nx \l_@@_tmp_tl
+ { \siunitx_number_output:N \l_@@_real_tl }
+ }
+ { \@@_format_auxii:n {#1} }
+ }
+ \tl_if_blank:nTF {#1}
+ { \siunitx_print_number:V \l_@@_tmp_tl }
+ { \siunitx_quantity_print:VV \l_@@_tmp_tl \l_@@_unit_tl }
+ }
+% \end{macrocode}
+% An imaginary part that is exactly $1$ is omitted, with only the complex
+% root printed. That means checking and removing a lone $1$ here.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_format_unary:nnnnnnn #1#2#3#4#5#6#7
+ {
+ \tl_set:Nx \l_@@_img_tl
+ {
+ \exp_not:n { {#1} {#2} }
+ \tl_if_blank:nTF {#4}
+ {
+ \str_if_eq:nnTF {#3} { 1 }
+ { { } { } }
+ { \exp_not:n { {#3} {#4} } }
+ }
+ { \exp_not:n { {#3} {#4} } }
+ \exp_not:n { {#5} {#6} {#7} }
+ }
+ }
+% \end{macrocode}
+% If we get to this stage we have both parts to a complex number. We
+% need to process both and do some massaging, then it's just a question
+% of reassembly with the right parts in the right places.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_format_auxii:n #1
+ {
+ \@@_format_units:n {#1}
+ \exp_after:wN \@@_drop_exponent:nnnnnnn \l_@@_real_tl
+ \exp_after:wN \@@_format_sign:nnnnnnn \l_@@_img_tl
+ \tl_set:Nx \l_@@_tmp_tl
+ { \siunitx_number_output:NN \l_@@_img_tl \q_nil }
+ \exp_after:wN \@@_extract_exponent:w \l_@@_tmp_tl \q_stop
+ \tl_set:Nx \l_@@_tmp_tl
+ {
+ \bool_lazy_and:nnTF
+ { \l_siunitx_number_bracket_ambiguous_bool }
+ { ! \tl_if_empty_p:N \l_@@_exp_tl }
+ { \@@_format_bracket:n }
+ { \use:n }
+ {
+ \siunitx_number_output:N \l_@@_real_tl
+ \exp_not:V \l_@@_sign_tl
+ \bool_if:NF \l_@@_root_after_bool
+ { \exp_not:V \l_@@_output_root_tl }
+ \exp_not:V \l_@@_tmp_tl
+ \bool_if:NT \l_@@_root_after_bool
+ { \exp_not:V \l_@@_output_root_tl }
+ }
+ \exp_not:V \l_@@_exp_tl
+ }
+ }
+% \end{macrocode}
+% No exponent for the real part.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_drop_exponent:nnnnnnn #1#2#3#4#5#6#7
+ { \tl_set:Nn \l_@@_real_tl { {#1} {#2} {#3} {#4} {#5} { } { 0 } } }
+% \end{macrocode}
+% Ensure the imaginary part has a sign, and also deal with the case
+% where there is no mantissa to print (as it is $1$).
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_format_sign:nnnnnnn #1#2#3#4#5#6#7
+ {
+ \tl_set:Nx \l_@@_img_tl
+ {
+ { }
+ { \tl_if_blank:nTF {#2} { + } { \exp_not:n {#2} } }
+ \tl_if_blank:nTF {#4}
+ {
+ \str_if_eq:nnTF {#3} { 1 }
+ { { } { } }
+ { \exp_not:n { {#3} {#4} } }
+ }
+ { \exp_not:n { {#3} {#4} } }
+ \exp_not:n { {#5} {#6} {#7} }
+ }
+ }
+% \end{macrocode}
+% Pull out the formatted exponent: we also need the sign.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_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_@@_sign_tl {#1#2}
+ \@@_extract_exponent_aux:nw {#3#4#5#6#7#8} #9 \q_stop
+ }
+\cs_new:Npn \@@_extract_exponent_aux:nw
+ #1#2 \q_nil #3 \q_nil #4 \q_stop
+ {
+ \tl_set:Nn \l_@@_tmp_tl {#1#2}
+ \tl_set:Nn \l_@@_exp_tl {#3#4}
+ }
+\cs_new_protected:Npn \@@_format_bracket:n #1
+ {
+ \exp_not:V \l_@@_bracket_open_tl
+ #1
+ \exp_not:V \l_@@_bracket_close_tl
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\@@_format_units:n}
+% \begin{macro}
+% {
+% \@@_format_combine-exponent:n ,
+% \@@_format_extract-exponent:n ,
+% \@@_format_input:n
+% }
+% \begin{macro}{\@@_format_extract-exponent:N}
+% \begin{macro}[EXP]{\@@_extract_exp:nnnnnnn}
+% Formatting units needs to know the settings from the main module, and
+% the flow is then much the same as in \pkg{siunitx-compound}. We only
+% have to watch the fact there are two numbers to format.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_format_units:n #1
+ {
+ \tl_if_blank:nTF {#1}
+ {
+ \siunitx_number_process:NN \l_@@_real_tl \l_@@_real_tl
+ \siunitx_number_process:NN \l_@@_img_tl \l_@@_img_tl
+ }
+ {
+ \use:c { @@_format_ \l_siunitx_quantity_prefix_mode_tl :n } {#1}
+ }
+ }
+\cs_new_protected:cpn { @@_format_combine-exponent:n } #1
+ {
+ \tl_if_empty:NF \l_@@_real_tl
+ { \siunitx_number_process:NN \l_@@_real_tl \l_@@_real_tl }
+ \siunitx_number_process:NN \l_@@_img_tl \l_@@_img_tl
+ \fp_set:Nn \l_@@_tmp_fp
+ { \exp_after:wN \@@_extract_exp:nnnnnnn \l_@@_img_tl }
+ \siunitx_unit_format_combine_exponent:nnN {#1}
+ \l_@@_tmp_fp \l_@@_unit_tl
+ }
+\cs_new_protected:cpx { @@_format_extract-exponent:n } #1
+ {
+ \exp_not:N \siunitx_unit_format_extract_prefixes:nNN {#1}
+ \exp_not:N \l_@@_unit_tl \exp_not:N \l_@@_tmp_fp
+ \exp_not:c { @@_format_extract-exponent:N }
+ \exp_not:N \l_@@_img_tl
+ \exp_not:N \tl_if_empty:NF \exp_not:N \l_@@_real_tl
+ {
+ \exp_not:c { @@_format_extract-exponent:N }
+ \exp_not:N \l_@@_real_tl
+ }
+ }
+\cs_new_protected:cpn { @@_format_extract-exponent:N } #1
+ {
+ \tl_set:Nx #1
+ { \siunitx_number_adjust_exponent:Nn #1 \l_@@_tmp_fp }
+ \siunitx_number_process:NN #1 #1
+ }
+\cs_new_protected:Npn \@@_format_input:n #1
+ {
+ \siunitx_number_process:NN \l_@@_real_tl \l_@@_real_tl
+ \siunitx_number_process:NN \l_@@_img_tl \l_@@_img_tl
+ \siunitx_unit_format:nN {#1} \l_@@_unit_tl
+ }
+\cs_new:Npn \@@_extract_exp:nnnnnnn #1#2#3#4#5#6#7 { #6#7 }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \subsection{Messages}
+%
+% \begin{macrocode}
+\msg_new:nnnn { siunitx } { invalid-complex-number }
+ { Invalid~complex-number~'#1'. }
+ {
+ The~input~'#1'~could~not~be~parsed~as~a~complex|number~following~the~
+ format~defined~in~module~documentation.
+ }
+% \end{macrocode}
+%
+% \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 }
+ {
+ complex-root-position = after-number ,
+ input-complex-root = ij ,
+ output-complex-root = \mathrm { i }
+ }
+% \end{macrocode}
+%
+% \begin{macrocode}
+%</package>
+% \end{macrocode}
+%
+% \end{implementation}
+%
+% \PrintIndex