diff options
Diffstat (limited to 'Master/texmf-dist/source/latex/l3kernel/l3fp-convert.dtx')
-rw-r--r-- | Master/texmf-dist/source/latex/l3kernel/l3fp-convert.dtx | 226 |
1 files changed, 115 insertions, 111 deletions
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3fp-convert.dtx b/Master/texmf-dist/source/latex/l3kernel/l3fp-convert.dtx index 057cef4b176..8f0c2848ea4 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3fp-convert.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3fp-convert.dtx @@ -35,8 +35,8 @@ %% % %<*driver> -\RequirePackage{l3names} -\GetIdInfo$Id: l3fp-convert.dtx 3986 2012-07-15 19:23:51Z joseph $ +\RequirePackage{l3bootstrap} +\GetIdInfo$Id: l3fp-convert.dtx 4090 2012-08-14 07:57:01Z joseph $ {L3 Floating-point conversion} \documentclass[full]{l3doc} \begin{document} @@ -66,9 +66,6 @@ % % \begin{documentation} % -% ^^A todo: tests -% ^^A todo: doc functions -% % \end{documentation} % % \begin{implementation} @@ -92,7 +89,7 @@ % as an end-delimiter for its first argument, and the second argument % is the same \texttt{loop} auxiliary. Once the last trailing zero is % reached, the second argument will be the \texttt{dot} auxiliary, -% which removes a trailing dot if any. We then cleanup with the +% which removes a trailing dot if any. We then clean-up with the % \texttt{end} auxiliary, keeping only the number. % \begin{macrocode} \cs_new:Npn \@@_trim_zeros:w #1 ; @@ -109,28 +106,17 @@ % % \subsection{Scientific notation} % -% \begin{variable}{\c_@@_scientific_inf_tl} -% Result of converting $\infty$ to a scientific representation: after -% triggering an \enquote{invalid operation} exception, -% \cs{fp_to_scientific:n} yields that result, larger than any finite -% floating point number. -% \begin{macrocode} -\tl_const:Nx \c_@@_scientific_inf_tl - { 1e \int_use:N \c_@@_max_exponent_int } -% \end{macrocode} -% \end{variable} -% -% \begin{macro} +% \begin{macro}[EXP] % {\fp_to_scientific:N, \fp_to_scientific:c, \fp_to_scientific:n} % The three public functions evaluate their argument, then pass it to % \cs{@@_to_scientific:w}. % \begin{macrocode} \cs_new:Npn \fp_to_scientific:N #1 { \exp_after:wN \@@_to_scientific:w #1 } \cs_generate_variant:Nn \fp_to_scientific:N { c } -\cs_new:Npn \fp_to_scientific:n #1 +\cs_new_nopar:Npn \fp_to_scientific:n { \exp_after:wN \@@_to_scientific:w - \tex_romannumeral:D -`0 \@@_parse:n {#1} + \tex_romannumeral:D -`0 \@@_parse:n } % \end{macrocode} % \end{macro} @@ -143,43 +129,63 @@ % } % Expressing an internal floating point number in scientific notation % is quite easy: no rounding, and the format is very well defined. -% First cater for the sign: negative numbers (|#2=2|) start with |-|. -% Then filter the special cases: we insert \cs{prg_do_nothing:} -% because \cs{@@_invalid_operation:Nnw} expands after taking one -% floating point argument. In the normal case, decrement the exponent -% and unbrace the $4$ brace groups, then in a second step grab the -% first digit (previously hidden in braces) to order the various parts -% correctly. Finally trim zeros. +% First cater for the sign: negative numbers ($|#2|=2$) start +% with~|-|; we then only need to care about positive numbers and +% \texttt{nan}. Then filter the special cases: $\pm0$~are represented +% as~|0|; infinities are converted to a number slightly larger than +% the largest after an \enquote{invalid_operation} exception; +% \texttt{nan} is represented as~|0| after an +% \enquote{invalid_operation} exception. In the normal case, +% decrement the exponent and unbrace the $4$ brace groups, then in a +% second step grab the first digit (previously hidden in braces) to +% order the various parts correctly. Finally trim zeros. The whole +% construction is within a call to \cs{tl_to_lowercase:n}, responsible +% for creating |e| with category \enquote{other}. % \begin{macrocode} -\cs_new:Npn \@@_to_scientific:w \s_@@ \@@_chk:w #1#2#3 ; +\group_begin: +\char_set_catcode_other:N E +\tl_to_lowercase:n { - \if_meaning:w 2 #2 \exp_after:wN - \tex_romannumeral:D -`0 \fi: - \if_case:w #1 \exp_stop_f: - \@@_case_return:nw { \exp_after:wN 0 } - \or: \exp_after:wN \@@_to_scientific_normal:wnnnnn - \or: - \@@_case_use:nw - { - \@@_invalid_operation:Nnw - \c_@@_scientific_inf_tl { fp_to_scientific } - } - \or: - \@@_case_use:nw - { \@@_invalid_operation:Nnw 0 { fp_to_scientific } } - \fi: - \s_@@ \@@_chk:w #1 #2 #3 ; \prg_do_nothing: - } -\cs_new:Npn \@@_to_scientific_normal:wnnnnn - \s_@@ \@@_chk:w 1 #1 #2 #3#4#5#6 ; \prg_do_nothing: - { - \if_int_compare:w #2 = \c_one - \exp_after:wN \@@_to_scientific_normal:wNw - \else: - \exp_after:wN \@@_to_scientific_normal:wNw - \exp_after:wN e - \int_use:N \__int_eval:w #2 - \c_one - \fi: - ; #3 #4 #5 #6 ; + \group_end: + \cs_new:Npn \@@_to_scientific:w \s_@@ \@@_chk:w #1#2 + { + \if_meaning:w 2 #2 \exp_after:wN - \tex_romannumeral:D -`0 \fi: + \if_case:w #1 \exp_stop_f: + \@@_case_return:nw { 0 } + \or: \exp_after:wN \@@_to_scientific_normal:wnnnnn + \or: + \@@_case_use:nw + { + \@@_invalid_operation:nnw + { + \exp_after:wN 1 + \exp_after:wN E + \int_use:N \c_@@_max_exponent_int + } + { fp_to_scientific } + } + \or: + \@@_case_use:nw + { + \@@_invalid_operation:nnw + { 0 } + { fp_to_scientific } + } + \fi: + \s_@@ \@@_chk:w #1 #2 + } + \cs_new:Npn \@@_to_scientific_normal:wnnnnn + \s_@@ \@@_chk:w 1 #1 #2 #3#4#5#6 ; + { + \if_int_compare:w #2 = \c_one + \exp_after:wN \@@_to_scientific_normal:wNw + \else: + \exp_after:wN \@@_to_scientific_normal:wNw + \exp_after:wN E + \int_use:N \__int_eval:w #2 - \c_one + \fi: + ; #3 #4 #5 #6 ; + } } \cs_new:Npn \@@_to_scientific_normal:wNw #1 ; #2#3; { \@@_trim_zeros:w #2.#3 ; #1 } @@ -188,22 +194,6 @@ % % \subsection{Decimal representation} % -% \begin{variable}{\c_@@_decimal_inf_tl} -% Result of converting $\infty$ to a decimal representation: after -% triggering an \enquote{invalid operation} exception, -% \cs{fp_to_decimal:n} yields a~$1$ followed by $\ExplSyntaxOn -% \int_use:N \c__fp_max_exponent_int$~$0$, larger than any finite -% floating point number. Since the expanded token list is very long, -% we use an \texttt{n}-type assignment. -% \begin{macrocode} -\tl_const:Nn \c_@@_decimal_inf_tl - { - \exp_after:wN \exp_after:wN \exp_after:wN 1 - \prg_replicate:nn \c_@@_max_exponent_int 0 - } -% \end{macrocode} -% \end{variable} -% % \begin{macro}[EXP] % {\fp_to_decimal:N, \fp_to_decimal:c, \fp_to_decimal:n} % All three public variants are based on the same \cs{@@_to_decimal:w} @@ -219,7 +209,7 @@ % \end{macrocode} % \end{macro} % -% \begin{macro}[EXP, aux] +% \begin{macro}[aux, EXP] % { % \@@_to_decimal:w, % \@@_to_decimal_normal:wnnnnn, @@ -228,35 +218,45 @@ % } % The structure is similar to \cs{@@_to_scientific:w}. Insert |-| for % negative numbers. Zero gives $0$, $\pm\infty$ and \nan{} yield an -% \enquote{invalid operation} exception. Normal numbers with an -% exponent in the range $[1,15]$ have that number of digits before the -% decimal separator: \enquote{decimate} them, and remove leading zeros -% with \cs{__int_value:w}, then trim trailing zeros and dot. Normal +% \enquote{invalid operation} exception; note that $\pm\infty$ +% produces a very large output, which we don't expand now since it +% most likely won't be needed. Normal numbers with an exponent in the +% range $[1,15]$ have that number of digits before the decimal +% separator: \enquote{decimate} them, and remove leading zeros with +% \cs{__int_value:w}, then trim trailing zeros and dot. Normal % numbers with an exponent $16$ or larger have no decimal separator, % we only need to add trailing zeros. When the exponent is % non-positive, the result should be $0.\meta{zeros}\meta{digits}$, % trimmed. % \begin{macrocode} -\cs_new:Npn \@@_to_decimal:w \s_@@ \@@_chk:w #1#2#3 ; +\cs_new:Npn \@@_to_decimal:w \s_@@ \@@_chk:w #1#2 { \if_meaning:w 2 #2 \exp_after:wN - \tex_romannumeral:D -`0 \fi: \if_case:w #1 \exp_stop_f: - \@@_case_return:nw { \exp_after:wN 0 } + \@@_case_return:nw { 0 } \or: \exp_after:wN \@@_to_decimal_normal:wnnnnn \or: \@@_case_use:nw { - \@@_invalid_operation:Nnw - \c_@@_decimal_inf_tl { fp_to_decimal } + \@@_invalid_operation:nnw + { + \exp_after:wN \exp_after:wN \exp_after:wN 1 + \prg_replicate:nn \c_@@_max_exponent_int 0 + } + { fp_to_decimal } } \or: \@@_case_use:nw - { \@@_invalid_operation:Nnw 0 { fp_to_decimal } } + { + \@@_invalid_operation:nnw + { 0 } + { fp_to_decimal } + } \fi: - \s_@@ \@@_chk:w #1 #2 #3 ; \prg_do_nothing: + \s_@@ \@@_chk:w #1 #2 } \cs_new:Npn \@@_to_decimal_normal:wnnnnn - \s_@@ \@@_chk:w 1 #1 #2 #3#4#5#6 ; \prg_do_nothing: + \s_@@ \@@_chk:w 1 #1 #2 #3#4#5#6 ; { \int_compare:nNnTF {#2} > \c_zero { @@ -309,14 +309,12 @@ % \end{macrocode} % \end{macro} % -% \begin{macro}[EXP, aux]{\@@_to_tl:w, \@@_to_tl_normal:nnnnn} +% \begin{macro}[aux, EXP]{\@@_to_tl:w, \@@_to_tl_normal:nnnnn} % A structure similar to \cs{@@_to_scientific:w} and % \cs{@@_to_decimal:w}, but without the \enquote{invalid operation} % exception. First filter special cases. We express normal numbers % in decimal notation if the exponent is in the range $[-2,16]$, and -% otherwise use scientific notation. The weird \cs{prg_do_nothing:} -% is needed because the \texttt{decimal} and \texttt{scientific} -% auxiliaries we use expect it. +% otherwise use scientific notation. % \begin{macrocode} \cs_new:Npn \@@_to_tl:w \s_@@ \@@_chk:w #1#2 { @@ -324,11 +322,11 @@ \if_case:w #1 \exp_stop_f: \@@_case_return:nw { 0 } \or: \exp_after:wN \@@_to_tl_normal:nnnnn - \or: \@@_case_return:nw { inf } - \else: \@@_case_return:nw { nan } + \or: \@@_case_return:nw { \tl_to_str:n {inf} } + \else: \@@_case_return:nw { \tl_to_str:n {nan} } \fi: } -\cs_new:Npn \@@_to_tl_normal:nnnnn #1#2 ; +\cs_new:Npn \@@_to_tl_normal:nnnnn #1 { \if_int_compare:w #1 > \c_sixteen \exp_after:wN \@@_to_scientific_normal:wnnnnn @@ -341,24 +339,29 @@ \exp_after:wN \@@_to_decimal_normal:wnnnnn \fi: \fi: - \s_@@ \@@_chk:w 1 0 {#1} #2 ; \prg_do_nothing: + \s_@@ \@@_chk:w 1 0 {#1} } % \end{macrocode} % \end{macro} % % \subsection{Formatting} % -% ^^A todo +% This is not implemented yet, as it is not yet clear what a correct +% interface would be, for this kind of structured conversion from a +% floating point (or other types of variables) to a string. Ideas +% welcome. % % \subsection{Convert to dimension or integer} % % \begin{macro}[EXP]{\fp_to_dim:N, \fp_to_dim:c, \fp_to_dim:n} % These three public functions rely on \cs{fp_to_decimal:n} -% internally. +% internally. We make sure to produce |pt| with category other. % \begin{macrocode} -\cs_new:Npn \fp_to_dim:N #1 { \fp_to_decimal:N #1 pt } +\cs_new:Npx \fp_to_dim:N #1 + { \exp_not:N \fp_to_decimal:N #1 \tl_to_str:n {pt} } \cs_generate_variant:Nn \fp_to_dim:N { c } -\cs_new:Npn \fp_to_dim:n #1 { \fp_to_decimal:n {#1} pt } +\cs_new:Npx \fp_to_dim:n #1 + { \exp_not:N \fp_to_decimal:n {#1} \tl_to_str:n {pt} } % \end{macrocode} % \end{macro} % @@ -385,7 +388,7 @@ \cs_new:Npn \@@_to_int:w #1; { \exp_after:wN \@@_to_decimal:w \tex_romannumeral:D -`0 - \@@_round:Nwn \@@_round_to_nearest:NNN #1; { 0 } \prg_do_nothing: + \@@_round:Nwn \@@_round_to_nearest:NNN #1; { 0 } } % \end{macrocode} % \end{macro} @@ -400,14 +403,12 @@ % \@@_from_dim_ii:wNNnnnnnn, % \@@_from_dim_iii:wnnnnwN, % } -% The dimension expression (which can in fact be a glue expression) -% is evaluated, converted to a number (\emph{i.e.}, expressed in -% scaled points), then multiplied by $2^{-16} = 0.0000152587890625$ -% to give a value expressed in points. We use the auxiliary function -% \begin{quote} -% \cs{@@_mul_npos:Nnwnw} \meta{sign} \newline -% ~~\Arg{exp_1} \meta{body_1} |;| \Arg{exp_2} \meta{body_2} |;| -% \end{quote} +% The dimension expression (which can in fact be a glue expression) is +% evaluated, converted to a number (\emph{i.e.}, expressed in scaled +% points), then multiplied by $2^{-16} = 0.0000152587890625$ to give a +% value expressed in points. The auxiliary \cs{@@_mul_npos_o:Nww} +% expects the desired \meta{final sign} and two floating point +% operands (of the form \cs{s_@@} \ldots{} |;|) as arguments. % \begin{macrocode} \cs_new:Npn \dim_to_fp:n #1 { @@ -417,8 +418,7 @@ \cs_new:Npn \@@_from_dim_test:N #1 { \if_meaning:w 0 #1 - \exp_after:wN \@@_use_i_until_s:nw - \exp_after:wN \c_zero_fp + \@@_case_return:nw \c_zero_fp \else: \if_meaning:w - #1 \exp_after:wN \@@_from_dim:Nw @@ -440,8 +440,9 @@ { \@@_from_dim_iii:wnnnnwN #1 {#2#300} {0000} ; } \cs_new:Npn \@@_from_dim_iii:wnnnnwN #1; #2#3#4#5#6; #7 { - \@@_mul_npos:Nnwnw #7 {#5} #1 ; - {-4} {1525} {8789} {0625} {0000} ; + \@@_mul_npos_o:Nww #7 + \s_@@ \@@_chk:w 1 #7 {#5} #1 ; + \s_@@ \@@_chk:w 1 0 {-4} {1525} {8789} {0625} {0000} ; } % \end{macrocode} % \end{macro} @@ -459,9 +460,12 @@ % \end{macro} % % \begin{macro}[EXP]{\fp_abs:n} -% Trivial but useful. +% Trivial but useful. See the implementation of \cs{fp_add:Nn} for an +% explanation of why to use \cs{@@_parse:n}, namely, for better error +% reporting. % \begin{macrocode} -\cs_new:Npn \fp_abs:n #1 { \fp_to_decimal:n { abs ( #1 ) } } +\cs_new:Npn \fp_abs:n #1 + { \fp_to_decimal:n { abs \@@_parse:n {#1} } } % \end{macrocode} % \end{macro} % @@ -473,4 +477,4 @@ % % \PrintChanges % -% \PrintIndex
\ No newline at end of file +% \PrintIndex |