From 134349701bddf7cbbacf6030c6b9f9838aff96fa Mon Sep 17 00:00:00 2001
From: Karl Berry <karl@freefriends.org>
Date: Mon, 23 Jul 2012 17:15:00 +0000
Subject: l3kernel 3990 (17jul12)

git-svn-id: svn://tug.org/texlive/trunk@27108 c570f23f-e606-0410-a88d-b1316a301751
---
 .../source/latex/l3kernel/l3fp-convert.dtx         | 476 +++++++++++++++++++++
 1 file changed, 476 insertions(+)
 create mode 100644 Master/texmf-dist/source/latex/l3kernel/l3fp-convert.dtx

(limited to 'Master/texmf-dist/source/latex/l3kernel/l3fp-convert.dtx')

diff --git a/Master/texmf-dist/source/latex/l3kernel/l3fp-convert.dtx b/Master/texmf-dist/source/latex/l3kernel/l3fp-convert.dtx
new file mode 100644
index 00000000000..057cef4b176
--- /dev/null
+++ b/Master/texmf-dist/source/latex/l3kernel/l3fp-convert.dtx
@@ -0,0 +1,476 @@
+% \iffalse meta-comment
+%
+%% File: l3fp-convert.dtx Copyright(C) 2011-2012 The LaTeX3 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
+%%
+%%    http://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 released version of this bundle is available from CTAN.
+%%
+%% -----------------------------------------------------------------------
+%%
+%% The development version of the bundle can be found at
+%%
+%%    http://www.latex-project.org/svnroot/experimental/trunk/
+%%
+%% for those people who are interested.
+%%
+%%%%%%%%%%%
+%% NOTE: %%
+%%%%%%%%%%%
+%%
+%%   Snapshots taken from the repository represent work in progress and may
+%%   not work or may contain conflicting material!  We therefore ask
+%%   people _not_ to put them into distributions, archives, etc. without
+%%   prior consultation with the LaTeX Project Team.
+%%
+%% -----------------------------------------------------------------------
+%%
+%
+%<*driver>
+\RequirePackage{l3names}
+\GetIdInfo$Id: l3fp-convert.dtx 3986 2012-07-15 19:23:51Z joseph $
+  {L3 Floating-point conversion}
+\documentclass[full]{l3doc}
+\begin{document}
+  \DocInput{\jobname.dtx}
+\end{document}
+%</driver>
+% \fi
+%
+% \title{^^A
+%   The \textsf{l3fp-convert} package\\ Floating point conversion^^A
+%   \thanks{This file describes v\ExplFileVersion,
+%     last revised \ExplFileDate.}^^A
+% }
+%
+% \author{^^A
+%  The \LaTeX3 Project\thanks
+%    {^^A
+%      E-mail:
+%        \href{mailto:latex-team@latex-project.org}
+%          {latex-team@latex-project.org}^^A
+%    }^^A
+% }
+%
+% \date{Released \ExplFileDate}
+%
+% \maketitle
+%
+% \begin{documentation}
+%
+% ^^A todo: tests
+% ^^A todo: doc functions
+%
+% \end{documentation}
+%
+% \begin{implementation}
+%
+% \section{\texttt{l3fp-convert} implementation}
+%
+%    \begin{macrocode}
+%<*initex|package>
+%    \end{macrocode}
+%
+%    \begin{macrocode}
+%<@@=fp>
+%    \end{macrocode}
+%
+% \subsection{Trimming trailing zeros}
+%
+% \begin{macro}[int, EXP]{\@@_trim_zeros:w}
+% \begin{macro}[aux, EXP]
+%   {\@@_trim_zeros_loop:w, \@@_trim_zeros_dot:w, \@@_trim_zeros_end:w}
+%   If |#1| ends with a $0$, the \texttt{loop} auxiliary takes that zero
+%   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
+%   \texttt{end} auxiliary, keeping only the number.
+%    \begin{macrocode}
+\cs_new:Npn \@@_trim_zeros:w #1 ;
+  {
+    \@@_trim_zeros_loop:w #1
+      ; \@@_trim_zeros_loop:w 0; \@@_trim_zeros_dot:w .; \s__stop
+  }
+\cs_new:Npn \@@_trim_zeros_loop:w #1 0; #2 { #2 #1 ; #2 }
+\cs_new:Npn \@@_trim_zeros_dot:w #1 .; { \@@_trim_zeros_end:w #1 ; }
+\cs_new:Npn \@@_trim_zeros_end:w #1 ; #2 \s__stop { #1 }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \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}
+%   {\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
+  {
+    \exp_after:wN \@@_to_scientific:w
+    \tex_romannumeral:D -`0 \@@_parse:n {#1}
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[aux, EXP]
+%   {
+%     \@@_to_scientific:w,
+%     \@@_to_scientific_normal:wnnnnn,
+%     \@@_to_scientific_normal:wNw
+%   }
+%   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.
+%    \begin{macrocode}
+\cs_new:Npn \@@_to_scientific:w \s_@@ \@@_chk:w #1#2#3 ;
+  {
+    \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 ;
+  }
+\cs_new:Npn \@@_to_scientific_normal:wNw #1 ; #2#3;
+  { \@@_trim_zeros:w #2.#3 ; #1 }
+%    \end{macrocode}
+% \end{macro}
+%
+% \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}
+%   after evaluating their argument to an internal floating point.
+%    \begin{macrocode}
+\cs_new:Npn \fp_to_decimal:N #1 { \exp_after:wN \@@_to_decimal:w #1 }
+\cs_generate_variant:Nn \fp_to_decimal:N { c }
+\cs_new_nopar:Npn \fp_to_decimal:n
+  {
+    \exp_after:wN \@@_to_decimal:w
+    \tex_romannumeral:D -`0 \@@_parse:n
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[EXP, aux]
+%   {
+%     \@@_to_decimal:w,
+%     \@@_to_decimal_normal:wnnnnn,
+%     \@@_to_decimal_large:Nnnw,
+%     \@@_to_decimal_huge:wnnnn,
+%   }
+%   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
+%   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 ;
+  {
+    \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_decimal_normal:wnnnnn
+    \or:
+      \@@_case_use:nw
+        {
+          \@@_invalid_operation:Nnw
+            \c_@@_decimal_inf_tl { fp_to_decimal }
+        }
+    \or:
+      \@@_case_use:nw
+        { \@@_invalid_operation:Nnw 0 { fp_to_decimal } }
+    \fi:
+    \s_@@ \@@_chk:w #1 #2 #3 ; \prg_do_nothing:
+  }
+\cs_new:Npn \@@_to_decimal_normal:wnnnnn
+    \s_@@ \@@_chk:w 1 #1 #2 #3#4#5#6 ; \prg_do_nothing:
+  {
+    \int_compare:nNnTF {#2} > \c_zero
+      {
+        \int_compare:nNnTF {#2} < \c_sixteen
+          {
+            \@@_decimate:nNnnnn { \c_sixteen - #2 }
+              \@@_to_decimal_large:Nnnw
+          }
+          {
+            \exp_after:wN \exp_after:wN
+            \exp_after:wN \@@_to_decimal_huge:wnnnn
+            \prg_replicate:nn { #2 - \c_sixteen } { 0 } ;
+          }
+        {#3} {#4} {#5} {#6}
+      }
+      {
+        \exp_after:wN \@@_trim_zeros:w
+        \exp_after:wN 0
+        \exp_after:wN .
+        \tex_romannumeral:D -`0 \prg_replicate:nn { - #2 } { 0 }
+        #3#4#5#6 ;
+      }
+  }
+\cs_new:Npn \@@_to_decimal_large:Nnnw #1#2#3#4;
+  {
+    \exp_after:wN \@@_trim_zeros:w \__int_value:w
+      \if_int_compare:w #2 > \c_zero
+        #2
+      \fi:
+      \exp_stop_f:
+      #3.#4 ;
+  }
+\cs_new:Npn \@@_to_decimal_huge:wnnnn #1; #2#3#4#5 { #2#3#4#5 #1 }
+%    \end{macrocode}
+% \end{macro}
+%
+% \subsection{Token list representation}
+%
+% \begin{macro}[EXP]{\fp_to_tl:N, \fp_to_tl:c, \fp_to_tl:n}
+%   These three public functions evaluate their argument, then pass it
+%   to \cs{@@_to_tl:w}.
+%    \begin{macrocode}
+\cs_new:Npn \fp_to_tl:N #1 { \exp_after:wN \@@_to_tl:w #1 }
+\cs_generate_variant:Nn \fp_to_tl:N { c }
+\cs_new_nopar:Npn \fp_to_tl:n
+  {
+    \exp_after:wN \@@_to_tl:w
+    \tex_romannumeral:D -`0 \@@_parse:n
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[EXP, aux]{\@@_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.
+%    \begin{macrocode}
+\cs_new:Npn \@@_to_tl: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_tl_normal:nnnnn
+    \or:   \@@_case_return:nw { inf }
+    \else: \@@_case_return:nw { nan }
+    \fi:
+  }
+\cs_new:Npn \@@_to_tl_normal:nnnnn #1#2 ;
+  {
+    \if_int_compare:w #1 > \c_sixteen
+      \exp_after:wN \@@_to_scientific_normal:wnnnnn
+    \else:
+      \if_int_compare:w #1 < - \c_two
+        \exp_after:wN \exp_after:wN
+        \exp_after:wN \@@_to_scientific_normal:wnnnnn
+      \else:
+        \exp_after:wN \exp_after:wN
+        \exp_after:wN \@@_to_decimal_normal:wnnnnn
+      \fi:
+    \fi:
+    \s_@@ \@@_chk:w 1 0 {#1} #2 ; \prg_do_nothing:
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \subsection{Formatting}
+%
+% ^^A todo
+%
+% \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.
+%    \begin{macrocode}
+\cs_new:Npn \fp_to_dim:N #1 { \fp_to_decimal:N #1 pt }
+\cs_generate_variant:Nn \fp_to_dim:N { c }
+\cs_new:Npn \fp_to_dim:n #1 { \fp_to_decimal:n {#1} pt }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[EXP]{\fp_to_int:N, \fp_to_int:c, \fp_to_int:n}
+%   These three public functions evaluate their argument, then pass it
+%   to \cs{fp_to_int:w}.
+%    \begin{macrocode}
+\cs_new:Npn \fp_to_int:N #1 { \exp_after:wN \@@_to_int:w #1 }
+\cs_generate_variant:Nn \fp_to_int:N { c }
+\cs_new_nopar:Npn \fp_to_int:n
+  {
+    \exp_after:wN \@@_to_int:w
+    \tex_romannumeral:D -`0 \@@_parse:n
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[aux, EXP]{\@@_to_int:w}
+%   To convert to an integer, first round to $0$ places (to the nearest
+%   integer), then express the result as a decimal number: the
+%   definition of \cs{@@_to_decimal:w} is such that there will be no
+%   trailing dot nor zero.
+%    \begin{macrocode}
+\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:
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \subsection{Convert from a dimension}
+%
+% \begin{macro}[EXP]{\dim_to_fp:n}
+% \begin{macro}[aux, EXP]
+%   {
+%     \@@_from_dim_test:N,
+%     \@@_from_dim:Nw,
+%     \@@_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}
+%    \begin{macrocode}
+\cs_new:Npn \dim_to_fp:n #1
+  {
+    \exp_after:wN \@@_from_dim_test:N
+    \__int_value:w \etex_glueexpr:D #1 ;
+  }
+\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
+    \else:
+      \if_meaning:w - #1
+        \exp_after:wN \@@_from_dim:Nw
+        \exp_after:wN 2
+        \__int_value:w
+      \else:
+        \exp_after:wN \@@_from_dim:Nw
+        \exp_after:wN 0
+        \__int_value:w #1
+      \fi:
+    \fi:
+  }
+\cs_new:Npn \@@_from_dim:Nw #1 #2;
+  {
+    \@@_pack_twice_four:wNNNNNNNN \@@_from_dim_ii:wNNnnnnnn ;
+    #2 000 0000 00 {10}987654321; #1
+  }
+\cs_new:Npn \@@_from_dim_ii:wNNnnnnnn #1; #2#3#4#5#6#7#8#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} ;
+  }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \subsection{Use and eval}
+%
+% \begin{macro}[EXP]{\fp_use:N, \fp_use:c, \fp_eval:n}
+%   Those public functions are simple copies of the decimal conversions.
+%    \begin{macrocode}
+\cs_new_eq:NN \fp_use:N \fp_to_decimal:N
+\cs_generate_variant:Nn \fp_use:N { c }
+\cs_new_eq:NN \fp_eval:n \fp_to_decimal:n
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[EXP]{\fp_abs:n}
+%   Trivial but useful.
+%    \begin{macrocode}
+\cs_new:Npn \fp_abs:n #1 { \fp_to_decimal:n { abs ( #1 ) } }
+%    \end{macrocode}
+% \end{macro}
+%
+%    \begin{macrocode}
+%</initex|package>
+%    \end{macrocode}
+%
+% \end{implementation}
+%
+% \PrintChanges
+%
+% \PrintIndex
\ No newline at end of file
-- 
cgit v1.2.3

