diff options
Diffstat (limited to 'macros/latex/contrib/siunitx/siunitx-complex.dtx')
-rw-r--r-- | macros/latex/contrib/siunitx/siunitx-complex.dtx | 849 |
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 |