From 6ac3dbed4b71022bd6bb0cc25e8fc3df81198498 Mon Sep 17 00:00:00 2001 From: Norbert Preining Date: Wed, 1 May 2024 03:00:54 +0000 Subject: CTAN sync 202405010300 --- macros/latex/contrib/l3kernel/l3fp-round.dtx | 592 --------------------------- 1 file changed, 592 deletions(-) delete mode 100644 macros/latex/contrib/l3kernel/l3fp-round.dtx (limited to 'macros/latex/contrib/l3kernel/l3fp-round.dtx') diff --git a/macros/latex/contrib/l3kernel/l3fp-round.dtx b/macros/latex/contrib/l3kernel/l3fp-round.dtx deleted file mode 100644 index bddb146be7..0000000000 --- a/macros/latex/contrib/l3kernel/l3fp-round.dtx +++ /dev/null @@ -1,592 +0,0 @@ -% \iffalse meta-comment -% -%% File: l3fp-round.dtx -% -% Copyright (C) 2011-2024 The LaTeX Project -% -% 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 "l3kernel bundle" (The Work in LPPL) -% and all files in that bundle must be distributed together. -% -% ----------------------------------------------------------------------- -% -% The development version of the bundle can be found at -% -% https://github.com/latex3/latex3 -% -% for those people who are interested. -% -%<*driver> -\documentclass[full,kernel]{l3doc} -\begin{document} - \DocInput{\jobname.dtx} -\end{document} -% -% \fi -% -% \title{^^A -% The \pkg{l3fp-round} module\\ Rounding floating points^^A -% } -% -% \author{^^A -% The \LaTeX{} Project\thanks -% {^^A -% E-mail: -% \href{mailto:latex-team@latex-project.org} -% {latex-team@latex-project.org}^^A -% }^^A -% } -% -% \date{Released 2024-03-14} -% -% \maketitle -% -% \begin{documentation} -% -% \end{documentation} -% -% \begin{implementation} -% -% \section{\pkg{l3fp-round} implementation} -% -% \begin{macrocode} -%<*package> -% \end{macrocode} -% -% \begin{macrocode} -%<@@=fp> -% \end{macrocode} -% -% ^^A todo: provide an interface for rounding modes. -% ^^A todo: provide a \l_@@_rounding_mode_int giving the current mode. -% ^^A todo: make transcendental function obey the correct rounding mode. -% ^^A todo: optimize all rounding functions for various rounding modes. -% ^^A todo: reduce the number of almost identical functions. -% -% \begin{macro}[EXP] -% { -% \@@_parse_word_trunc:N, -% \@@_parse_word_floor:N, -% \@@_parse_word_ceil:N -% } -% \begin{macrocode} -\cs_new:Npn \@@_parse_word_trunc:N - { \@@_parse_function:NNN \@@_round_o:Nw \@@_round_to_zero:NNN } -\cs_new:Npn \@@_parse_word_floor:N - { \@@_parse_function:NNN \@@_round_o:Nw \@@_round_to_ninf:NNN } -\cs_new:Npn \@@_parse_word_ceil:N - { \@@_parse_function:NNN \@@_round_o:Nw \@@_round_to_pinf:NNN } -% \end{macrocode} -% \end{macro} -% -% \begin{macro}[EXP] -% { -% \@@_parse_word_round:N, \@@_parse_round:Nw, -% } -% \begin{macrocode} -\cs_new:Npn \@@_parse_word_round:N #1#2 - { - \@@_parse_function:NNN - \@@_round_o:Nw \@@_round_to_nearest:NNN #1 - #2 - } -\cs_new:Npn \@@_parse_round:Nw #1 #2 \@@_round_to_nearest:NNN #3#4 - { #2 #1 #3 } - -% \end{macrocode} -% \end{macro} -% -% \subsection{Rounding tools} -% -% \begin{variable}{\c_@@_five_int} -% This is used as the half-point for which numbers are rounded -% up/down. -% \begin{macrocode} -\int_const:Nn \c_@@_five_int { 5 } -% \end{macrocode} -% \end{variable} -% -% Floating point operations often yield a result that cannot be exactly -% represented in a significand with $16$ digits. In that case, we need to -% round the exact result to a representable number. The \textsc{ieee} -% standard defines four rounding modes: -% \begin{itemize} -% \item Round to nearest: round to the representable floating point -% number whose absolute difference with the exact result is the -% smallest. If the exact result lies exactly at the mid-point -% between two consecutive representable floating point numbers, -% round to the floating point number whose last digit is even. -% \item Round towards negative infinity: round to the greatest -% floating point number not larger than the exact result. -% \item Round towards zero: round to a floating point number with the -% same sign as the exact result, with the largest absolute value not -% larger than the absolute value of the exact result. -% \item Round towards positive infinity: round to the least floating -% point number not smaller than the exact result. -% \end{itemize} -% This is not fully implemented in \pkg{l3fp} yet, and transcendental -% functions fall back on the \enquote{round to nearest} mode. All -% rounding for basic algebra is done through the functions defined in -% this module, which can be redefined to change their rounding behaviour -% (but there is not interface for that yet). -% -% The rounding tools available in this module are many variations on a -% base function \cs{@@_round:NNN}, which expands to |0\exp_stop_f:| or -% |1\exp_stop_f:| depending on whether the final result should be rounded up -% or down. -% \begin{itemize} -% \item \cs{@@_round:NNN} \meta{sign} \meta{digit_1} \meta{digit_2} -% can expand to |0\exp_stop_f:| or |1\exp_stop_f:|. -% \item \cs{@@_round_s:NNNw} \meta{sign} \meta{digit_1} \meta{digit_2} -% \meta{more digits}|;| can expand to |0\exp_stop_f:;| or |1\exp_stop_f:;|. -% \item \cs{@@_round_neg:NNN} \meta{sign} \meta{digit_1} \meta{digit_2} -% can expand to |0\exp_stop_f:| or |1\exp_stop_f:|. -% \end{itemize} -% See implementation comments for details on the syntax. -% -% \begin{macro}[rEXP]{\@@_round:NNN} -% \begin{macro}[rEXP] -% { -% \@@_round_to_nearest:NNN, -% \@@_round_to_nearest_ninf:NNN, -% \@@_round_to_nearest_zero:NNN, -% \@@_round_to_nearest_pinf:NNN, -% \@@_round_to_ninf:NNN, -% \@@_round_to_zero:NNN, -% \@@_round_to_pinf:NNN -% } -% \begin{syntax} -% \cs{@@_round:NNN} \meta{final sign} \meta{digit_1} \meta{digit_2} -% \end{syntax} -% If rounding the number $\meta{final sign} -% \meta{digit_1}.\meta{digit_2}$ to an integer rounds it towards zero -% (truncates it), this function expands to |0\exp_stop_f:|, and otherwise -% to |1\exp_stop_f:|. Typically used within the scope of an -% \cs{@@_int_eval:w}, to add~$1$ if needed, and thereby round -% correctly. The result depends on the rounding mode. -% -% It is very important that \meta{final sign} be the final sign of the -% result. Otherwise, the result would be incorrect in the case of -% rounding towards~$-\infty$ or towards~$+\infty$. Also recall that -% \meta{final sign} is~$0$ for positive, and~$2$ for negative. -% -% By default, the functions below return |0\exp_stop_f:|, but this is -% superseded by \cs{@@_round_return_one:}, which instead returns -% |1\exp_stop_f:|, expanding everything and removing |0\exp_stop_f:| in the -% process. In the case of rounding towards~$\pm\infty$ or -% towards~$0$, this is not really useful, but it prepares us for the -% \enquote{round to nearest, ties to even} mode. -% -% The \enquote{round to nearest} mode is the default. If the -% \meta{digit_2} is larger than~$5$, then round up. If it is less -% than~$5$, round down. If it is exactly $5$, then round such that -% \meta{digit_1} plus the result is even. In other words, round up if -% \meta{digit_1} is odd. -% -% The \enquote{round to nearest} mode has three variants, which differ -% in how ties are rounded: down towards $-\infty$, truncated towards $0$, -% or up towards $+\infty$. -% \begin{macrocode} -\cs_new:Npn \@@_round_return_one: - { \exp_after:wN 1 \exp_after:wN \exp_stop_f: \exp:w } -\cs_new:Npn \@@_round_to_ninf:NNN #1 #2 #3 - { - \if_meaning:w 2 #1 - \if_int_compare:w #3 > \c_zero_int - \@@_round_return_one: - \fi: - \fi: - \c_zero_int - } -\cs_new:Npn \@@_round_to_zero:NNN #1 #2 #3 { \c_zero_int } -\cs_new:Npn \@@_round_to_pinf:NNN #1 #2 #3 - { - \if_meaning:w 0 #1 - \if_int_compare:w #3 > \c_zero_int - \@@_round_return_one: - \fi: - \fi: - \c_zero_int - } -\cs_new:Npn \@@_round_to_nearest:NNN #1 #2 #3 - { - \if_int_compare:w #3 > \c_@@_five_int - \@@_round_return_one: - \else: - \if_meaning:w 5 #3 - \if_int_odd:w #2 \exp_stop_f: - \@@_round_return_one: - \fi: - \fi: - \fi: - \c_zero_int - } -\cs_new:Npn \@@_round_to_nearest_ninf:NNN #1 #2 #3 - { - \if_int_compare:w #3 > \c_@@_five_int - \@@_round_return_one: - \else: - \if_meaning:w 5 #3 - \if_meaning:w 2 #1 - \@@_round_return_one: - \fi: - \fi: - \fi: - \c_zero_int - } -\cs_new:Npn \@@_round_to_nearest_zero:NNN #1 #2 #3 - { - \if_int_compare:w #3 > \c_@@_five_int - \@@_round_return_one: - \fi: - \c_zero_int - } -\cs_new:Npn \@@_round_to_nearest_pinf:NNN #1 #2 #3 - { - \if_int_compare:w #3 > \c_@@_five_int - \@@_round_return_one: - \else: - \if_meaning:w 5 #3 - \if_meaning:w 0 #1 - \@@_round_return_one: - \fi: - \fi: - \fi: - \c_zero_int - } -\cs_new_eq:NN \@@_round:NNN \@@_round_to_nearest:NNN -% \end{macrocode} -% \end{macro} -% \end{macro} -% -% \begin{macro}[EXP]{\@@_round_s:NNNw} -% \begin{syntax} -% \cs{@@_round_s:NNNw} \meta{final sign} \meta{digit} \meta{more digits} |;| -% \end{syntax} -% Similar to \cs{@@_round:NNN}, but with an extra semicolon, this -% function expands to |0\exp_stop_f:;| if rounding $\meta{final sign} -% \meta{digit}.\meta{more digits}$ to an integer truncates, and to -% |1\exp_stop_f:;| otherwise. The \meta{more digits} part must be a digit, -% followed by something that does not overflow a \cs{int_use:N} -% \cs{@@_int_eval:w} construction. The only relevant information about -% this piece is whether it is zero or not. -% \begin{macrocode} -\cs_new:Npn \@@_round_s:NNNw #1 #2 #3 #4; - { - \exp_after:wN \@@_round:NNN - \exp_after:wN #1 - \exp_after:wN #2 - \int_value:w \@@_int_eval:w - \if_int_odd:w 0 \if_meaning:w 0 #3 1 \fi: - \if_meaning:w 5 #3 1 \fi: - \exp_stop_f: - \if_int_compare:w \@@_int_eval:w #4 > \c_zero_int - 1 + - \fi: - \fi: - #3 - ; - } -% \end{macrocode} -% \end{macro} -% -% \begin{macro}[EXP]{\@@_round_digit:Nw} -% \begin{syntax} -% \cs{int_value:w} \cs{@@_round_digit:Nw} \meta{digit} \meta{int expr} |;| -% \end{syntax} -% This function should always be called within an \cs{int_value:w} -% or \cs{@@_int_eval:w} expansion; it may add an extra -% \cs{@@_int_eval:w}, which means that the integer or integer -% expression should not be ended with a synonym of \tn{relax}, but -% with a semi-colon for instance. -% \begin{macrocode} -\cs_new:Npn \@@_round_digit:Nw #1 #2; - { - \if_int_odd:w \if_meaning:w 0 #1 1 \else: - \if_meaning:w 5 #1 1 \else: - 0 \fi: \fi: \exp_stop_f: - \if_int_compare:w \@@_int_eval:w #2 > \c_zero_int - \@@_int_eval:w 1 + - \fi: - \fi: - #1 - } -% \end{macrocode} -% \end{macro} -% -% \begin{macro}[EXP]{\@@_round_neg:NNN} -% \begin{macro}[EXP] -% { -% \@@_round_to_nearest_neg:NNN, -% \@@_round_to_nearest_ninf_neg:NNN, -% \@@_round_to_nearest_zero_neg:NNN, -% \@@_round_to_nearest_pinf_neg:NNN, -% \@@_round_to_ninf_neg:NNN, -% \@@_round_to_zero_neg:NNN, -% \@@_round_to_pinf_neg:NNN -% } -% \begin{syntax} -% \cs{@@_round_neg:NNN} \meta{final sign} \meta{digit_1} \meta{digit_2} -% \end{syntax} -% This expands to |0\exp_stop_f:| or |1\exp_stop_f:| after doing the following -% test. Starting from a number of -% the form $ \meta{final sign}0.\meta{15 digits}\meta{digit_1} $ with exactly -% $15$ (non-all-zero) digits before \meta{digit_1}, subtract from it -% $\meta{final sign}0.0\ldots{}0\meta{digit_2}$, where there are $16$~zeros. -% If in the current rounding mode the result should be rounded down, -% then this function returns |1\exp_stop_f:|. Otherwise, \emph{i.e.}, -% if the result is rounded back to the first operand, then this function -% returns |0\exp_stop_f:|. -% -% It turns out that this negative \enquote{round to nearest} -% is identical to the positive one. And this is the default mode. -% \begin{macrocode} -\cs_new_eq:NN \@@_round_to_ninf_neg:NNN \@@_round_to_pinf:NNN -\cs_new:Npn \@@_round_to_zero_neg:NNN #1 #2 #3 - { - \if_int_compare:w #3 > \c_zero_int - \@@_round_return_one: - \fi: - \c_zero_int - } -\cs_new_eq:NN \@@_round_to_pinf_neg:NNN \@@_round_to_ninf:NNN -\cs_new_eq:NN \@@_round_to_nearest_neg:NNN \@@_round_to_nearest:NNN -\cs_new_eq:NN \@@_round_to_nearest_ninf_neg:NNN - \@@_round_to_nearest_pinf:NNN -\cs_new:Npn \@@_round_to_nearest_zero_neg:NNN #1 #2 #3 - { - \if_int_compare:w #3 < \c_@@_five_int \else: - \@@_round_return_one: - \fi: - \c_zero_int - } -\cs_new_eq:NN \@@_round_to_nearest_pinf_neg:NNN - \@@_round_to_nearest_ninf:NNN -\cs_new_eq:NN \@@_round_neg:NNN \@@_round_to_nearest_neg:NNN -% \end{macrocode} -% \end{macro} -% \end{macro} -% -% \subsection{The \texttt{round} function} -% -% ^^A todo: This macro is intermingled with l3fp-parse. -% ^^A todo: Add explanations. -% \begin{macro}[EXP]{\@@_round_o:Nw, \@@_round_aux_o:Nw} -% First check that all arguments are floating point numbers. -% The |trunc|, |ceil| and |floor| functions expect one or two -% arguments (the second is $0$ by default), and the |round| function -% also accepts a third argument (\texttt{nan} by default), which -% changes |#1| from \cs{@@_round_to_nearest:NNN} to one of its -% analogues. -% \begin{macrocode} -\cs_new:Npn \@@_round_o:Nw #1 - { - \@@_parse_function_all_fp_o:fnw - { \@@_round_name_from_cs:N #1 } - { \@@_round_aux_o:Nw #1 } - } -\cs_new:Npn \@@_round_aux_o:Nw #1#2 @ - { - \if_case:w - \@@_int_eval:w \@@_array_count:n {#2} \@@_int_eval_end: - \@@_round_no_arg_o:Nw #1 \exp:w - \or: \@@_round:Nwn #1 #2 {0} \exp:w - \or: \@@_round:Nww #1 #2 \exp:w - \else: \@@_round:Nwww #1 #2 @ \exp:w - \fi: - \exp_after:wN \exp_end: - } -% \end{macrocode} -% \end{macro} -% -% \begin{macro}[EXP]{\@@_round_no_arg_o:Nw} -% \begin{macrocode} -\cs_new:Npn \@@_round_no_arg_o:Nw #1 - { - \cs_if_eq:NNTF #1 \@@_round_to_nearest:NNN - { \@@_error:nnnn { num-args } { round () } { 1 } { 3 } } - { - \@@_error:nffn { num-args } - { \@@_round_name_from_cs:N #1 () } { 1 } { 2 } - } - \exp_after:wN \c_nan_fp - } -% \end{macrocode} -% \end{macro} -% -% \begin{macro}[EXP]{\@@_round:Nwww} -% Having three arguments is only allowed for |round|, not |trunc|, -% |ceil|, |floor|, so check for that case. If all is well, construct -% one of \cs{@@_round_to_nearest:NNN}, \cs{@@_round_to_nearest_zero:NNN}, -% \cs{@@_round_to_nearest_ninf:NNN}, \cs{@@_round_to_nearest_pinf:NNN} -% and act accordingly. -% \begin{macrocode} -\cs_new:Npn \@@_round:Nwww #1#2 ; #3 ; \s_@@ \@@_chk:w #4#5#6 ; #7 @ - { - \cs_if_eq:NNTF #1 \@@_round_to_nearest:NNN - { - \tl_if_empty:nTF {#7} - { - \exp_args:Nc \@@_round:Nww - { - @@_round_to_nearest - \if_meaning:w 0 #4 _zero \else: - \if_case:w #5 \exp_stop_f: _pinf \or: \else: _ninf \fi: \fi: - :NNN - } - #2 ; #3 ; - } - { - \@@_error:nnnn { num-args } { round () } { 1 } { 3 } - \exp_after:wN \c_nan_fp - } - } - { - \@@_error:nffn { num-args } - { \@@_round_name_from_cs:N #1 () } { 1 } { 2 } - \exp_after:wN \c_nan_fp - } - } -% \end{macrocode} -% \end{macro} -% -% \begin{macro}[EXP]{\@@_round_name_from_cs:N} -% \begin{macrocode} -\cs_new:Npn \@@_round_name_from_cs:N #1 - { - \cs_if_eq:NNTF #1 \@@_round_to_zero:NNN { trunc } - { - \cs_if_eq:NNTF #1 \@@_round_to_ninf:NNN { floor } - { - \cs_if_eq:NNTF #1 \@@_round_to_pinf:NNN { ceil } - { round } - } - } - } -% \end{macrocode} -% \end{macro} -% -% \begin{macro}[EXP]{\@@_round:Nww, \@@_round:Nwn} -% \begin{macro}[EXP] -% { -% \@@_round_normal:NwNNnw , -% \@@_round_normal:NnnwNNnn , -% \@@_round_pack:Nw , -% \@@_round_normal:NNwNnn , -% \@@_round_normal_end:wwNnn , -% \@@_round_special:NwwNnn , -% \@@_round_special_aux:Nw -% } -% If the number of digits to round to is an integer or infinity all is -% good; if it is \texttt{nan} then just produce a \texttt{nan}; -% otherwise invalid as we have something like |round(1,3.14)| where -% the number of digits is not an integer. -% \begin{macrocode} -\cs_new:Npn \@@_round:Nww #1#2 ; #3 ; - { - \@@_small_int:wTF #3; { \@@_round:Nwn #1#2; } - { - \if:w 3 \@@_kind:w #3 ; - \exp_after:wN \use_i:nn - \else: - \exp_after:wN \use_ii:nn - \fi: - { \exp_after:wN \c_nan_fp } - { - \@@_invalid_operation_tl_o:ff - { \@@_round_name_from_cs:N #1 } - { \@@_array_to_clist:n { #2; #3; } } - } - } - } -\cs_new:Npn \@@_round:Nwn #1 \s_@@ \@@_chk:w #2#3#4; #5 - { - \if_meaning:w 1 #2 - \exp_after:wN \@@_round_normal:NwNNnw - \exp_after:wN #1 - \int_value:w #5 - \else: - \exp_after:wN \@@_exp_after_o:w - \fi: - \s_@@ \@@_chk:w #2#3#4; - } -\cs_new:Npn \@@_round_normal:NwNNnw #1#2 \s_@@ \@@_chk:w 1#3#4#5; - { - \@@_decimate:nNnnnn { \c_@@_prec_int - #4 - #2 } - \@@_round_normal:NnnwNNnn #5 #1 #3 {#4} {#2} - } -\cs_new:Npn \@@_round_normal:NnnwNNnn #1#2#3#4; #5#6 - { - \exp_after:wN \@@_round_normal:NNwNnn - \int_value:w \@@_int_eval:w - \if_int_compare:w #2 > \c_zero_int - 1 \int_value:w #2 - \exp_after:wN \@@_round_pack:Nw - \int_value:w \@@_int_eval:w 1#3 + - \else: - \if_int_compare:w #3 > \c_zero_int - 1 \int_value:w #3 + - \fi: - \fi: - \exp_after:wN #5 - \exp_after:wN #6 - \use_none:nnnnnnn #3 - #1 - \@@_int_eval_end: - 0000 0000 0000 0000 ; #6 - } -\cs_new:Npn \@@_round_pack:Nw #1 - { \if_meaning:w 2 #1 + 1 \fi: \@@_int_eval_end: } -\cs_new:Npn \@@_round_normal:NNwNnn #1 #2 - { - \if_meaning:w 0 #2 - \exp_after:wN \@@_round_special:NwwNnn - \exp_after:wN #1 - \fi: - \@@_pack_twice_four:wNNNNNNNN - \@@_pack_twice_four:wNNNNNNNN - \@@_round_normal_end:wwNnn - ; #2 - } -\cs_new:Npn \@@_round_normal_end:wwNnn #1;#2;#3#4#5 - { - \exp_after:wN \@@_exp_after_o:w \exp:w \exp_end_continue_f:w - \@@_sanitize:Nw #3 #4 ; #1 ; - } -\cs_new:Npn \@@_round_special:NwwNnn #1#2;#3;#4#5#6 - { - \if_meaning:w 0 #1 - \@@_case_return:nw - { \exp_after:wN \@@_zero_fp:N \exp_after:wN #4 } - \else: - \exp_after:wN \@@_round_special_aux:Nw - \exp_after:wN #4 - \int_value:w \@@_int_eval:w 1 - \if_meaning:w 1 #1 -#6 \else: +#5 \fi: - \fi: - ; - } -\cs_new:Npn \@@_round_special_aux:Nw #1#2; - { - \exp_after:wN \@@_exp_after_o:w \exp:w \exp_end_continue_f:w - \@@_sanitize:Nw #1#2; {1000}{0000}{0000}{0000}; - } -% \end{macrocode} -% \end{macro} -% \end{macro} -% -% \begin{macrocode} -% -% \end{macrocode} -% -% \end{implementation} -% -% \PrintChanges -% -% \PrintIndex -- cgit v1.2.3