summaryrefslogtreecommitdiff
path: root/macros/latex/contrib/l3kernel/l3fp-round.dtx
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2024-05-01 03:00:54 +0000
committerNorbert Preining <norbert@preining.info>2024-05-01 03:00:54 +0000
commit6ac3dbed4b71022bd6bb0cc25e8fc3df81198498 (patch)
tree74689e5368262d351f68fb5d1f0fbea88a3af701 /macros/latex/contrib/l3kernel/l3fp-round.dtx
parent3bb814fe836cd59db56f2f5d07f69cb531ed25e0 (diff)
CTAN sync 202405010300HEADmaster
Diffstat (limited to 'macros/latex/contrib/l3kernel/l3fp-round.dtx')
-rw-r--r--macros/latex/contrib/l3kernel/l3fp-round.dtx592
1 files changed, 0 insertions, 592 deletions
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}
-%</driver>
-% \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}
-%</package>
-% \end{macrocode}
-%
-% \end{implementation}
-%
-% \PrintChanges
-%
-% \PrintIndex