[latex3-commits] [l3svn] branch master updated: Add \fp_step_... (closes #319)

Bruno Le Floch blflatex at gmail.com
Tue Nov 22 03:23:53 CET 2016


This code seems very reasonable and no obvious speedups except using
more private fp functions.

One question is whether (conceptually) we should be using additions as
Joseph did or multiplication by integers.  This affects rounding.

Say we had floats with 2 significant digits only (for simplicity of the
example).  Then going from 0 to 9.9 in steps of 0.98 gives

0, 0.98, 2, 3, 4, 5, 6, 7, 8, 9 using addition, and

0, 0.98, 2, 2.9, 3.9, 4.9, 5.9, 6.9, 7.8, 8.8, 9.8 using multiplication
(so one more term).

Bruno


On 11/21/2016 12:04 PM, noreply at latex-project.org wrote:
> This is an automated email from the git hooks/post-receive script.
> 
> joseph pushed a commit to branch master
> in repository l3svn.
> 
> The following commit(s) were added to refs/heads/master by this push:
>        new  9125b99   Add \fp_step_... (closes #319)
> 9125b99 is described below
> 
> commit 9125b99074c5c359cd3a5925e1cc61d0c36e1e17
> Author: Joseph Wright <joseph.wright at morningstar2.co.uk>
> Date:   Mon Nov 21 17:04:08 2016 +0000
> 
>     Add \fp_step_... (closes #319)
>     
>     This might not be the most efficient approach: Bruno knows more
>     about fp internals than me!
> ---
>  l3kernel/l3fp-logic.dtx                 |   68 +++++++++++++++++++++++++++++++
>  l3kernel/l3fp.dtx                       |   44 ++++++++++++++++++++
>  l3kernel/testfiles/m3expl001.luatex.tlg |    7 ++++
>  l3kernel/testfiles/m3expl001.ptex.tlg   |    7 ++++
>  l3kernel/testfiles/m3expl001.tlg        |    7 ++++
>  l3kernel/testfiles/m3expl001.uptex.tlg  |    7 ++++
>  l3kernel/testfiles/m3expl001.xetex.tlg  |    7 ++++
>  l3kernel/testfiles/m3expl003.luatex.tlg |    7 ++++
>  l3kernel/testfiles/m3expl003.ptex.tlg   |    7 ++++
>  l3kernel/testfiles/m3expl003.tlg        |    7 ++++
>  l3kernel/testfiles/m3expl003.uptex.tlg  |    7 ++++
>  l3kernel/testfiles/m3expl003.xetex.tlg  |    7 ++++
>  l3kernel/testfiles/m3fp-logic004.lvt    |   36 ++++++++++++++++
>  l3kernel/testfiles/m3fp-logic004.tlg    |   35 ++++++++++++++++
>  14 files changed, 253 insertions(+)
> 
> diff --git a/l3kernel/l3fp-logic.dtx b/l3kernel/l3fp-logic.dtx
> index 0e0a6ac..aa0702e 100644
> --- a/l3kernel/l3fp-logic.dtx
> +++ b/l3kernel/l3fp-logic.dtx
> @@ -316,6 +316,74 @@
>  %    \end{macrocode}
>  % \end{macro}
>  %
> +% \begin{macro}[EXP]{\fp_step_function:nnnN, \fp_step_function:nnnc}
> +% \begin{macro}[EXP, aux]{\@@_step:wwwN}
> +% \begin{macro}[EXP, aux]{\@@_step:NnnnN, \@@_step:NfnnN}
> +%   The approach here is much the same as \cs{int_step_function:nnnN} except we
> +%   do not have a convenient low-level way to evaluation each argument to give
> +%   a pure number. Instead, the internal parser is used to leave values in the
> +%   internal format (and avoid a more expensive \texttt{f}-type expansion of
> +%   multiple uses of \texttt{fp_eval:n}).
> +%    \begin{macrocode}
> +\cs_new:Npn \fp_step_function:nnnN #1#2#3
> +  {
> +    \exp_after:wN \@@_step:wwwN
> +      \exp:w \exp_end_continue_f:w \@@_parse_o:n {#1} :
> +      \exp:w \exp_end_continue_f:w \@@_parse_o:n {#2} :
> +      \exp:w \exp_end_continue_f:w \@@_parse:n {#3} :
> +  }
> +\cs_generate_variant:Nn \fp_step_function:nnnN { nnnc }
> +%    \end{macrocode}
> +%   Here, |#1| will be passed to the output on the first pass of the loop.
> +%   To avoid this being in internal form, an \texttt{f}-type expansion is used
> +%   here on that value only. The second and third arguments will be converted
> +%   during the loop itself.
> +%    \begin{macrocode}
> +\cs_new:Npn \@@_step:wwwN #1 : #2 : #3 : #4
> +  {
> +    \fp_compare:nNnTF {#2} > 0
> +      { \@@_step:NfnnN > }
> +      {
> +        \fp_compare:nNnTF {#2} = 0
> +          {
> +            \__msg_kernel_expandable_error:nnn { kernel } { zero-step } {#4}
> +            \use_none:nnnn
> +          }
> +          { \@@_step:NfnnN < }
> +      }
> +      { \fp_eval:n {#1} } {#2} {#3} #4
> +  }
> +
> +\cs_new:Npn \@@_step:NnnnN #1#2#3#4#5
> +  {
> +    \fp_compare:nNnF {#2} #1 {#4}
> +      {
> +        #5 {#2}
> +        \@@_step:NfnnN
> +          #1 { \fp_eval:n { #2 + #3 } } {#3} {#4} #5
> +      }
> +  }
> +\cs_generate_variant:Nn \@@_step:NnnnN { Nf }
> +%    \end{macrocode}
> +% \end{macro}
> +% \end{macro}
> +% \end{macro}
> +% \begin{macro}{\fp_step_inline:nnnn}
> +%   As for \cs{int_step_inline:nnnn}, create a global function and apply it,
> +%   following up with a break point.
> +%    \begin{macrocode}
> +\cs_new_protected:Npn \fp_step_inline:nnnn #1#2#3#4
> +  {
> +    \int_gincr:N \g__prg_map_int
> +    \cs_gset_protected:cpn { __prg_map_ \int_use:N \g__prg_map_int :w }
> +      ##1 {#4}
> +    \fp_step_function:nnnc {#1} {#2} {#3}
> +      { __prg_map_ \int_use:N \g__prg_map_int :w }
> +    \__prg_break_point:Nn \scan_stop: { \int_gdecr:N \g__prg_map_int }
> +  }
> +%    \end{macrocode}
> +% \end{macro}
> +%
>  % \subsection{Extrema}
>  %
>  % \begin{macro}[int, EXP]{\@@_minmax_o:Nw}
> diff --git a/l3kernel/l3fp.dtx b/l3kernel/l3fp.dtx
> index 996e4f5..a9c7385 100644
> --- a/l3kernel/l3fp.dtx
> +++ b/l3kernel/l3fp.dtx
> @@ -541,6 +541,50 @@
>  %   \texttt{false}.
>  % \end{function}
>  %
> +% \begin{function}[added = 2016-11-21, rEXP]
> +%   {\fp_step_function:nnnN}
> +%   \begin{syntax}
> +%     \cs{fp_step_function:nnnN} \Arg{initial value} \Arg{step} \Arg{final value} \meta{function}
> +%   \end{syntax}
> +%   This function first evaluates the \meta{initial value}, \meta{step}
> +%   and \meta{final value}, all of which should be floating point expressions.
> +%   The \meta{function} is then placed in front of each \meta{value}
> +%   from the \meta{initial value} to the \meta{final value} in turn
> +%   (using \meta{step} between each \meta{value}).  The \meta{step} must
> +%   be non-zero.  If the \meta{step} is positive, the loop stops when
> +%   the \meta{value} becomes larger than the \meta{final value}.  If the
> +%   \meta{step} is negative, the loop stops when the \meta{value}
> +%   becomes smaller than the \meta{final value}.  The \meta{function}
> +%   should absorb one numerical argument. For example
> +%   \begin{verbatim}
> +%     \cs_set:Npn \my_func:n #1 { [I~saw~#1] \quad }
> +%     \fp_step_function:nnnN { 1.0 } { 0.1 } { 1.5 } \my_func:n
> +%   \end{verbatim}
> +%   would print
> +%   \begin{quote}
> +%     [I saw 1.0] \quad
> +%     [I saw 1.1] \quad
> +%     [I saw 1.2] \quad
> +%     [I saw 1.3] \quad
> +%     [I saw 1.4] \quad
> +%     [I saw 1.5] \quad
> +%   \end{quote}
> +% \end{function}
> +%
> +% \begin{function}[added = 2016-11-21]
> +%   {\fp_step_inline:nnnn}
> +%   \begin{syntax}
> +%     \cs{\fp_step_inline:nnnn} \Arg{initial value} \Arg{step} \Arg{final value} \Arg{code}
> +%   \end{syntax}
> +%   This function first evaluates the \meta{initial value}, \meta{step}
> +%   and \meta{final value}, all of which should be floating point expressions.
> +%   Then for each \meta{value} from the \meta{initial value} to the
> +%   \meta{final value} in turn (using \meta{step} between each
> +%   \meta{value}), the \meta{code} is inserted into the input stream
> +%   with |#1| replaced by the current \meta{value}.  Thus the
> +%   \meta{code} should define a function of one argument~(|#1|).
> +% \end{function}
> +%
>  % \section{Some useful constants, and scratch variables}
>  %
>  % \begin{variable}[added = 2012-05-08]{\c_zero_fp, \c_minus_zero_fp}
> diff --git a/l3kernel/testfiles/m3expl001.luatex.tlg b/l3kernel/testfiles/m3expl001.luatex.tlg
> index 9c97cf7..496a6e1 100644
> --- a/l3kernel/testfiles/m3expl001.luatex.tlg
> +++ b/l3kernel/testfiles/m3expl001.luatex.tlg
> @@ -3731,6 +3731,13 @@ Defining \fp_do_until:nNnn on line ...
>  Defining \fp_do_while:nNnn on line ...
>  Defining \fp_until_do:nNnn on line ...
>  Defining \fp_while_do:nNnn on line ...
> +Defining \fp_step_function:nnnN on line ...
> +Defining \exp_args:Nnnnc on line ...
> +Defining \fp_step_function:nnnc on line ...
> +Defining \__fp_step:wwwN on line ...
> +Defining \__fp_step:NnnnN on line ...
> +Defining \__fp_step:NfnnN on line ...
> +Defining \fp_step_inline:nnnn on line ...
>  Defining \__fp_minmax_o:Nw on line ...
>  Defining \__fp_minmax_loop:Nww on line ...
>  Defining \__fp_minmax_auxi:ww on line ...
> diff --git a/l3kernel/testfiles/m3expl001.ptex.tlg b/l3kernel/testfiles/m3expl001.ptex.tlg
> index 4a0c2bf..b9f7c52 100644
> --- a/l3kernel/testfiles/m3expl001.ptex.tlg
> +++ b/l3kernel/testfiles/m3expl001.ptex.tlg
> @@ -3722,6 +3722,13 @@ Defining \fp_do_until:nNnn on line ...
>  Defining \fp_do_while:nNnn on line ...
>  Defining \fp_until_do:nNnn on line ...
>  Defining \fp_while_do:nNnn on line ...
> +Defining \fp_step_function:nnnN on line ...
> +Defining \exp_args:Nnnnc on line ...
> +Defining \fp_step_function:nnnc on line ...
> +Defining \__fp_step:wwwN on line ...
> +Defining \__fp_step:NnnnN on line ...
> +Defining \__fp_step:NfnnN on line ...
> +Defining \fp_step_inline:nnnn on line ...
>  Defining \__fp_minmax_o:Nw on line ...
>  Defining \__fp_minmax_loop:Nww on line ...
>  Defining \__fp_minmax_auxi:ww on line ...
> diff --git a/l3kernel/testfiles/m3expl001.tlg b/l3kernel/testfiles/m3expl001.tlg
> index faee6dc..92b7758 100644
> --- a/l3kernel/testfiles/m3expl001.tlg
> +++ b/l3kernel/testfiles/m3expl001.tlg
> @@ -3722,6 +3722,13 @@ Defining \fp_do_until:nNnn on line ...
>  Defining \fp_do_while:nNnn on line ...
>  Defining \fp_until_do:nNnn on line ...
>  Defining \fp_while_do:nNnn on line ...
> +Defining \fp_step_function:nnnN on line ...
> +Defining \exp_args:Nnnnc on line ...
> +Defining \fp_step_function:nnnc on line ...
> +Defining \__fp_step:wwwN on line ...
> +Defining \__fp_step:NnnnN on line ...
> +Defining \__fp_step:NfnnN on line ...
> +Defining \fp_step_inline:nnnn on line ...
>  Defining \__fp_minmax_o:Nw on line ...
>  Defining \__fp_minmax_loop:Nww on line ...
>  Defining \__fp_minmax_auxi:ww on line ...
> diff --git a/l3kernel/testfiles/m3expl001.uptex.tlg b/l3kernel/testfiles/m3expl001.uptex.tlg
> index 6d1132a..49c2635 100644
> --- a/l3kernel/testfiles/m3expl001.uptex.tlg
> +++ b/l3kernel/testfiles/m3expl001.uptex.tlg
> @@ -3722,6 +3722,13 @@ Defining \fp_do_until:nNnn on line ...
>  Defining \fp_do_while:nNnn on line ...
>  Defining \fp_until_do:nNnn on line ...
>  Defining \fp_while_do:nNnn on line ...
> +Defining \fp_step_function:nnnN on line ...
> +Defining \exp_args:Nnnnc on line ...
> +Defining \fp_step_function:nnnc on line ...
> +Defining \__fp_step:wwwN on line ...
> +Defining \__fp_step:NnnnN on line ...
> +Defining \__fp_step:NfnnN on line ...
> +Defining \fp_step_inline:nnnn on line ...
>  Defining \__fp_minmax_o:Nw on line ...
>  Defining \__fp_minmax_loop:Nww on line ...
>  Defining \__fp_minmax_auxi:ww on line ...
> diff --git a/l3kernel/testfiles/m3expl001.xetex.tlg b/l3kernel/testfiles/m3expl001.xetex.tlg
> index 8c0422d..891c5a4 100644
> --- a/l3kernel/testfiles/m3expl001.xetex.tlg
> +++ b/l3kernel/testfiles/m3expl001.xetex.tlg
> @@ -3729,6 +3729,13 @@ Defining \fp_do_until:nNnn on line ...
>  Defining \fp_do_while:nNnn on line ...
>  Defining \fp_until_do:nNnn on line ...
>  Defining \fp_while_do:nNnn on line ...
> +Defining \fp_step_function:nnnN on line ...
> +Defining \exp_args:Nnnnc on line ...
> +Defining \fp_step_function:nnnc on line ...
> +Defining \__fp_step:wwwN on line ...
> +Defining \__fp_step:NnnnN on line ...
> +Defining \__fp_step:NfnnN on line ...
> +Defining \fp_step_inline:nnnn on line ...
>  Defining \__fp_minmax_o:Nw on line ...
>  Defining \__fp_minmax_loop:Nww on line ...
>  Defining \__fp_minmax_auxi:ww on line ...
> diff --git a/l3kernel/testfiles/m3expl003.luatex.tlg b/l3kernel/testfiles/m3expl003.luatex.tlg
> index 3ef272b..42bd013 100644
> --- a/l3kernel/testfiles/m3expl003.luatex.tlg
> +++ b/l3kernel/testfiles/m3expl003.luatex.tlg
> @@ -3732,6 +3732,13 @@ Defining \fp_do_until:nNnn on line ...
>  Defining \fp_do_while:nNnn on line ...
>  Defining \fp_until_do:nNnn on line ...
>  Defining \fp_while_do:nNnn on line ...
> +Defining \fp_step_function:nnnN on line ...
> +Defining \exp_args:Nnnnc on line ...
> +Defining \fp_step_function:nnnc on line ...
> +Defining \__fp_step:wwwN on line ...
> +Defining \__fp_step:NnnnN on line ...
> +Defining \__fp_step:NfnnN on line ...
> +Defining \fp_step_inline:nnnn on line ...
>  Defining \__fp_minmax_o:Nw on line ...
>  Defining \__fp_minmax_loop:Nww on line ...
>  Defining \__fp_minmax_auxi:ww on line ...
> diff --git a/l3kernel/testfiles/m3expl003.ptex.tlg b/l3kernel/testfiles/m3expl003.ptex.tlg
> index c3c92bf..b130bde 100644
> --- a/l3kernel/testfiles/m3expl003.ptex.tlg
> +++ b/l3kernel/testfiles/m3expl003.ptex.tlg
> @@ -3723,6 +3723,13 @@ Defining \fp_do_until:nNnn on line ...
>  Defining \fp_do_while:nNnn on line ...
>  Defining \fp_until_do:nNnn on line ...
>  Defining \fp_while_do:nNnn on line ...
> +Defining \fp_step_function:nnnN on line ...
> +Defining \exp_args:Nnnnc on line ...
> +Defining \fp_step_function:nnnc on line ...
> +Defining \__fp_step:wwwN on line ...
> +Defining \__fp_step:NnnnN on line ...
> +Defining \__fp_step:NfnnN on line ...
> +Defining \fp_step_inline:nnnn on line ...
>  Defining \__fp_minmax_o:Nw on line ...
>  Defining \__fp_minmax_loop:Nww on line ...
>  Defining \__fp_minmax_auxi:ww on line ...
> diff --git a/l3kernel/testfiles/m3expl003.tlg b/l3kernel/testfiles/m3expl003.tlg
> index 94c79ad..19fdc27 100644
> --- a/l3kernel/testfiles/m3expl003.tlg
> +++ b/l3kernel/testfiles/m3expl003.tlg
> @@ -3723,6 +3723,13 @@ Defining \fp_do_until:nNnn on line ...
>  Defining \fp_do_while:nNnn on line ...
>  Defining \fp_until_do:nNnn on line ...
>  Defining \fp_while_do:nNnn on line ...
> +Defining \fp_step_function:nnnN on line ...
> +Defining \exp_args:Nnnnc on line ...
> +Defining \fp_step_function:nnnc on line ...
> +Defining \__fp_step:wwwN on line ...
> +Defining \__fp_step:NnnnN on line ...
> +Defining \__fp_step:NfnnN on line ...
> +Defining \fp_step_inline:nnnn on line ...
>  Defining \__fp_minmax_o:Nw on line ...
>  Defining \__fp_minmax_loop:Nww on line ...
>  Defining \__fp_minmax_auxi:ww on line ...
> diff --git a/l3kernel/testfiles/m3expl003.uptex.tlg b/l3kernel/testfiles/m3expl003.uptex.tlg
> index d25c26e..89fc56f 100644
> --- a/l3kernel/testfiles/m3expl003.uptex.tlg
> +++ b/l3kernel/testfiles/m3expl003.uptex.tlg
> @@ -3723,6 +3723,13 @@ Defining \fp_do_until:nNnn on line ...
>  Defining \fp_do_while:nNnn on line ...
>  Defining \fp_until_do:nNnn on line ...
>  Defining \fp_while_do:nNnn on line ...
> +Defining \fp_step_function:nnnN on line ...
> +Defining \exp_args:Nnnnc on line ...
> +Defining \fp_step_function:nnnc on line ...
> +Defining \__fp_step:wwwN on line ...
> +Defining \__fp_step:NnnnN on line ...
> +Defining \__fp_step:NfnnN on line ...
> +Defining \fp_step_inline:nnnn on line ...
>  Defining \__fp_minmax_o:Nw on line ...
>  Defining \__fp_minmax_loop:Nww on line ...
>  Defining \__fp_minmax_auxi:ww on line ...
> diff --git a/l3kernel/testfiles/m3expl003.xetex.tlg b/l3kernel/testfiles/m3expl003.xetex.tlg
> index 5dea49b..7523b71 100644
> --- a/l3kernel/testfiles/m3expl003.xetex.tlg
> +++ b/l3kernel/testfiles/m3expl003.xetex.tlg
> @@ -3730,6 +3730,13 @@ Defining \fp_do_until:nNnn on line ...
>  Defining \fp_do_while:nNnn on line ...
>  Defining \fp_until_do:nNnn on line ...
>  Defining \fp_while_do:nNnn on line ...
> +Defining \fp_step_function:nnnN on line ...
> +Defining \exp_args:Nnnnc on line ...
> +Defining \fp_step_function:nnnc on line ...
> +Defining \__fp_step:wwwN on line ...
> +Defining \__fp_step:NnnnN on line ...
> +Defining \__fp_step:NfnnN on line ...
> +Defining \fp_step_inline:nnnn on line ...
>  Defining \__fp_minmax_o:Nw on line ...
>  Defining \__fp_minmax_loop:Nww on line ...
>  Defining \__fp_minmax_auxi:ww on line ...
> diff --git a/l3kernel/testfiles/m3fp-logic004.lvt b/l3kernel/testfiles/m3fp-logic004.lvt
> new file mode 100644
> index 0000000..b2be436
> --- /dev/null
> +++ b/l3kernel/testfiles/m3fp-logic004.lvt
> @@ -0,0 +1,36 @@
> +%
> +% Copyright (C) 2016 LaTeX3 Project
> +%
> +
> +\documentclass{minimal}
> +\input{regression-test}
> +
> +\RequirePackage[check-declarations,log-functions]{expl3}
> +
> +\begin{document}
> +\START
> +\AUTHOR{Joseph Wright}
> +\ExplSyntaxOn
> +
> +
> +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
> +\TESTEXP { fp_step_function }
> +  {
> +    \fp_step_function:nnnN { 0 } { 0.1 }  { 1 } \TYPE
> +    \NEWLINE
> +    \fp_step_function:nnnN { 0 } { -0.1 } { 1 } \TYPE
> +    \NEWLINE
> +    \fp_step_function:nnnN { 1 } { -0.1 } { 0 } \TYPE
> +    \NEWLINE
> +    \fp_step_function:nnnN { 1 } { 0.1 }  { 0 } \TYPE
> +  }
> +
> +\TEST { fp_step_inline }
> +  {
> +    \fp_step_inline:nnnn { 0 } { 0.1 }  { 1 } { \TYPE {#1} }
> +    \fp_step_inline:nnnn { 0 } { -0.1 } { 1 } { \TYPE {#1} }
> +    \fp_step_inline:nnnn { 1 } { -0.1 } { 0 } { \TYPE {#1} }
> +    \fp_step_inline:nnnn { 1 } { 0.1 }  { 0 } { \TYPE {#1} }
> +  }
> +
> +\END
> diff --git a/l3kernel/testfiles/m3fp-logic004.tlg b/l3kernel/testfiles/m3fp-logic004.tlg
> new file mode 100644
> index 0000000..22c44c9
> --- /dev/null
> +++ b/l3kernel/testfiles/m3fp-logic004.tlg
> @@ -0,0 +1,35 @@
> +This is a generated file for the LaTeX (2e + expl3) validation system.
> +Don't change this file in any respect.
> +Author: Joseph Wright
> +============================================================
> +TEST 1: fp_step_function
> +============================================================
> +00.10.20.30.40.50.60.70.80.91
> +10.90.80.70.60.50.40.30.20.10
> +============================================================
> +============================================================
> +TEST 2: fp_step_inline
> +============================================================
> +0
> +0.1
> +0.2
> +0.3
> +0.4
> +0.5
> +0.6
> +0.7
> +0.8
> +0.9
> +1
> +1
> +0.9
> +0.8
> +0.7
> +0.6
> +0.5
> +0.4
> +0.3
> +0.2
> +0.1
> +0
> +============================================================
> 



More information about the latex3-commits mailing list