% \iffalse
%% File: l3intexpr.dtx Copyright (C) 2009 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 ``expl3 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|package>
\RequirePackage{l3names}
%</driver|package>
%\fi
\GetIdInfo$Id: l3intexpr.dtx 1086 2009-03-20 19:29:35Z morten $
       {L3 Integer Expressions}
%\iffalse
%<*driver>
%\fi
\ProvidesFile{\filename.\filenameext}
  [\filedate\space v\fileversion\space\filedescription]
%\iffalse
\documentclass[full]{l3doc}
\begin{document}
\DocInput{\filename.\filenameext}
\end{document}
%</driver>
% \fi
%
%
% \title{The \textsf{l3intexpr} package\thanks{This file
%         has version number \fileversion, last
%         revised \filedate.}\\
% Integer expressions}
% \author{\Team}
% \date{\filedate}
% \maketitle
%
% \begin{documentation}
%
% This module sets up evaluation of integer expressions and allows
% mixing |int| and |num| registers.
%
% An integer expression is one that contains integers in the form of
% numbers, registers containg numbers, i.e., |int| and |num| registers
% plus constants like |\c_one|, standard operators "+", "-", "/" and
% "*" and parentheses to group sub-expressions.
%
% \section{Functions}
%
% \begin{function}{%
%                  \intexpr_eval:n / (EXP)
% }
% \begin{syntax}
%    "\intexpr_eval:n"   \Arg{int~expr}
% \end{syntax}
% The result of this expansion is a properly terminated <number>,
% i.e., one that can be used with "\if_case:w" and others. For example,
% \begin{quote}
%   |\intexpr_eval:n{ 5 + 4*3 - (3+4*5) }|
% \end{quote}
% evaluates to $-6$.  The result is returned after two expansions so
% if you find that you need to pass on the result to another function
% using the expansion engine, the recommendation is to use an "f" type
% expansion if in an expandable context or "x" otherwise.
% \end{function}
%
%
% \begin{function}{%
%                  \intexpr_compare_p:n / (EXP) |
%                  \intexpr_compare:n / (TF)(EXP)
% }
% \begin{syntax}
%    "\intexpr_compare_p:n"   \Arg{<int~expr1> <rel> <int~expr2>}
% \end{syntax}
% Compares <int~expr1> with <int~expr2> using C-like relational
% operators, i.e.
% \begin{center}
% \begin{tabular}{ll@{\hspace{2cm}}ll}
% Less than & "<" & Less than or equal & "<=" \\
% Greater than & "<" & Greater than or equal  &  ">=" \\
% Equal &  "==" or "=" & Not equal & "!="
% \end{tabular}
% \end{center}
% Both integer expressions are evaluated fully in the process. Note
% the syntax, which allows natural input in the style of
% \begin{quote}
%    |\intexpr_compare_p:n {5+3 != \l_tmpb_int}|
% \end{quote}
% "=" is added for the sake of \TeX\ users accustomed to using a
% single equal sign.
% \end{function}
% 
%
% \begin{function}{%
%                  \intexpr_compare_p:nNn / (EXP) |
%                  \intexpr_compare:nNn / (TF)(EXP)
% }
% \begin{syntax}
%    "\intexpr_compare_p:nNn"   \Arg{int~expr1}<rel>\Arg{int~expr2}
% \end{syntax}
% Compares <int~expr1> with <int~expr2> using one of the relations
% "=", ">" or "<". This is faster than the variant above but at the
% cost of requiring a little more typing and not supporting the
% extended set of relational operators. Note that if both expressions
% are normal integer variables as in
% \begin{quote}
% "\intexpr_compare:nNnTF \l_temp_int < \c_zero {negative}{non-negative}"
% \end{quote}
% you can safely omit the braces.
% \end{function}
%
%
% \begin{function}{%
%                  \intexpr_max:nn / (EXP)|
%                  \intexpr_min:nn / (EXP)|
% }
% \begin{syntax}
%   "\intexpr_max:nn"   \Arg{int~expr1} \Arg{int~expr2}
% \end{syntax}
% Return the largest or smallest of two integer expressions.
% \end{function}
%
% \begin{function}{%
%                  \intexpr_abs:n / (EXP)|
% }
% \begin{syntax}
%   "\intexpr_abs:n"   \Arg{int~expr}
% \end{syntax}
% Return the numerical value of an integer expression.
% \end{function}
%
% \begin{function}{%
%                  \intexpr_if_odd:n / (EXP)(TF) |
%                  \intexpr_if_odd_p:n / (EXP) |
%                  \intexpr_if_even:n / (EXP)(TF) |
%                  \intexpr_if_even_p:n / (EXP) |
% }
% \begin{syntax}
%   "\intexpr_if_odd:nTF"   \Arg{int~expr} \Arg{true} \Arg{false}
% \end{syntax}
% These functions test if an integer expression is even or odd.
% \end{function}
%
%
%
%
%
%
% \begin{function}{%
%                  \intexpr_div_truncate:nn / (EXP) |
%                  \intexpr_div_round:nn / (EXP) |
%                  \intexpr_mod:nn / (EXP) |
% }
% \begin{syntax}
%   "\intexpr_div_truncate:n"   \Arg{int~expr} \Arg{int~expr} \\
%   "\intexpr_mod:nn"   \Arg{int~expr} \Arg{int~expr}
% \end{syntax}
% If
% you want the result of a division to be truncated use
% "\intexpr_div_truncate:nn". "\intexpr_div_round:nn" is added for
% completeness. "\intexpr_mod:nn" returns the remainder of a division. 
% \end{function}
%
%
%
%
%
%
%
%
%
%
%
% \section{Primitive functions}
%
%
% \begin{function}{%
%                  \intexpr_value:w |
% }
% \begin{syntax}
%   "\intexpr_value:w" <integer>  \\ 
%   "\intexpr_value:w" <tokens>  <optional space>
% \end{syntax}
% Expands <tokens> until an <integer> is formed. One space may be
% gobbled in the process. 
% \begin{texnote}
% This is the \TeX{} primitive \tn{number}.
% \end{texnote}
% \end{function}
%
% \begin{function}{%
%                  \intexpr_eval:w |
%                  \intexpr_eval_end: |
% }
% \begin{syntax}
%   "\intexpr_eval:w" <int expr> "\intexpr_eval_end:"
% \end{syntax}
% Evaluates <int expr>. The evaluation stops when an
% unexpandable token of catcode other than 12 is reached or
% "\intexpr_end:" is read. The latter is gobbled by the scanner
% mechanism.
% \begin{texnote}
% This is the \eTeX{} primitive \tn{numexpr}.
% \end{texnote}
% \end{function}
%
% \begin{function}{%
%                  \if_intexpr_compare:w |
% }
% \begin{syntax}
%   "\if_intexpr_compare:w" <number1> <rel> <number2> <true> "\else:" <false> "\fi:"
% \end{syntax}
% Compare two numbers. It is recommended to use "\intexpr_eval:n" to
% correctly evaluate and terminate these numbers. <rel> is one of
% "<", "=" or ">" with catcode 12.
% \begin{texnote}
% This is the \TeX{} primitive \tn{ifnum}.
% \end{texnote}
% \end{function}
%
% \begin{function}{%
%                  \if_intexpr_odd:w |
% }
% \begin{syntax}
%   "\if_intexpr_odd:w" <number>  <true> "\else:" <false> "\fi:"
% \end{syntax}
% Execute <true> if <number> is odd, <false> otherwise.
% \begin{texnote}
% This is the \TeX{} primitive \tn{ifodd}.
% \end{texnote}
% \end{function}
%
% \begin{function}{%
%                  \if_intexpr_case:w |
%                  \or: |
% }
% \begin{syntax}
%   "\if_intexpr_case:w" <number> <case0> "\or:" <case1> "\or:" "..." "\else:"
%   <default> "\fi:"
% \end{syntax}
% Chooses case <number>. If you wish to use negative numbers as well,
% you can offset them with "\intexpr_eval:n".
% \begin{texnote}
% These are the \TeX{} primitives \tn{ifcase} and \tn{or}.
% \end{texnote}
% \end{function}
%
%^^A Keep the documenation-checking happy
%\ExplSyntaxOn
%\seq_gput_right:Nx \g_doc_macros_seq { \token_to_str:N \or: } 
%\ExplSyntaxOff
%
% \begin{function}{%
%                  \intexpr_while_do:nn |
%                  \intexpr_until_do:nn |
%                  \intexpr_do_while:nn |
%                  \intexpr_do_until:nn |
% }
% \begin{syntax}
%   "\intexpr_while_do:nn"   \Arg{<int~expr1> <rel> <int~expr2>} \Arg{code}
% \end{syntax}
% "\intexpr_while_do:nn" tests the integer expressions against each
% other using a C-like <rel> as in "\intexpr_compare_p:n" and if true
% performs the <code> until the test fails. "\intexpr_do_while:nn" is
% similar but executes the <code> first and then performs the check,
% thus ensuring that the body is executed at least once. The `until'
% versions are similar but continue the loop as long as the test is
% false. They could be omitted as it is just a matter of switching the
% arguments in the test.
% \end{function}
%
% \begin{function}{%
%                  \intexpr_while_do:nNnn |
%                  \intexpr_until_do:nNnn |
%                  \intexpr_do_while:nNnn |
%                  \intexpr_do_until:nNnn |
% }
% \begin{syntax}
%   "\intexpr_while_do:nNnn"   <int expr> <rel> <int~expr> \Arg{code}
% \end{syntax}
% Exactly as above but instead using the syntax of
% "\intexpr_compare_p:nNn".
% \end{function}
%
%
%
%
%
% \end{documentation}
%
% \begin{implementation}
%
% \section{\pkg{l3intexpr} implementation}
%
%
%    We start by ensuring that the required packages are loaded.
%    \begin{macrocode}
%<*package>
\ProvidesExplPackage
  {\filename}{\filedate}{\fileversion}{\filedescription}
\package_check_loaded_expl:
%</package>
%<*initex|package>
%    \end{macrocode}
%
% \begin{macro}{\intexpr_value:w}
% \begin{macro}{\intexpr_eval:n,\intexpr_eval:w,\intexpr_eval_end:}
% \begin{macro}{\if_intexpr_compare:w}
% \begin{macro}{\if_intexpr_odd:w}
% \begin{macro}{\if_intexpr_case:w}
%   Here are the remaining primitives for number comparisons and
%   expressions.
%    \begin{macrocode}
\cs_set_eq:NN \intexpr_value:w \tex_number:D
\cs_set_eq:NN \intexpr_eval:w \etex_numexpr:D
\cs_set_protected:Npn \intexpr_eval_end: {\tex_relax:D}
\cs_set_eq:NN \if_intexpr_compare:w \tex_ifnum:D
\cs_set_eq:NN \if_intexpr_odd:w \tex_ifodd:D
\cs_set_eq:NN \if_intexpr_case:w \tex_ifcase:D
\cs_set:Npn \intexpr_eval:n #1{
  \intexpr_value:w \intexpr_eval:w #1\intexpr_eval_end:
}
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
%
%
%
%
%
%
% \begin{macro}{\intexpr_compare_p:n}
% \begin{macro}[TF]{\intexpr_compare:n}
% Comparison tests using a simple syntax where only one set of braces
% is required and additional operators such as "!=" and ">=" are
% supported. First some notes on the idea behind this. We wish to
% support writing code like
% \begin{verbatim}
% \intexpr_compare_p:n { 5 + \l_tmpa_int != 4 - \l_tmpb_int }
% \end{verbatim}
% In other words, we want to somehow add the missing "\intexpr_eval:w"
% where required.  We can start evaluating from the left using
% "\intexpr:w", and we know that since the relation symbols "<", ">",
% "=" and "!" are not allowed in such expressions, they will terminate
% the expression. Therefore, we first let \TeX\ evaluate this left
% hand side of the (in)equality.
%    \begin{macrocode}
\prg_set_conditional:Npnn \intexpr_compare:n #1{p,TF,T,F}{
  \exp_after:wN \intexpr_compare_auxi:w \intexpr_value:w
    \intexpr_eval:w #1\q_stop
}
%    \end{macrocode}
% Then the next step is to figure out which relation we should use, so
% we have to somehow get rid of the first evaluation so that we can
% see what stopped it. "\tex_romannumeral:D" is handy here since its
% expansion given a non-positive number is \m{null}. We therefore
% simply check if the first token of the left hand side evaluation is
% a minus. If not, we insert it and issue "\tex_romannumeral:D",
% thereby ridding us of the left hand side evaluation. We do however
% save it for later.
%    \begin{macrocode}
\cs_set:Npn \intexpr_compare_auxi:w #1#2\q_stop{
   \exp_after:wN   \intexpr_compare_auxii:w \tex_romannumeral:D
   \if:w #1- \else: -\fi: #1#2 \q_stop #1#2 \q_nil
}
%    \end{macrocode}
% This leaves the first relation symbol in front and assuming the
% right hand side has been input, at least one other token as well. We
% support the following forms: |=|, |<|, |>| and the extended |!=|,
% |==|, |<=| and |>=|. All the extended forms have an extra |=| so we
% check if that is present as well. Then use specific function to
% perform the test.
%    \begin{macrocode}
\cs_set:Npn \intexpr_compare_auxii:w #1#2#3\q_stop{ 
   \use:c{
     intexpr_compare_ 
     #1  \if_meaning:w =#2 =  \fi:
     :w}  
}
%    \end{macrocode}
% The actual comparisons are then simple function calls, using the
% relation as delimiter for a delimited argument.
% Equality is easy:
%    \begin{macrocode}
\cs_set:cpn {intexpr_compare_=:w} #1=#2\q_nil{
  \if_intexpr_compare:w #1=\intexpr_eval:w #2 \intexpr_eval_end: 
    \prg_return_true: \else: \prg_return_false: \fi:
}
%    \end{macrocode}
% So is the one using |==| -- we just have to use |==| in the
% parameter text.
%    \begin{macrocode}
\cs_set:cpn {intexpr_compare_==:w} #1==#2\q_nil{
  \if_intexpr_compare:w #1=\intexpr_eval:w #2 \intexpr_eval_end: 
  \prg_return_true: \else: \prg_return_false: \fi:
}
%    \end{macrocode}
% Not equal is just about reversing the truth value.
%    \begin{macrocode}
\cs_set:cpn {intexpr_compare_!=:w} #1!=#2\q_nil{
  \if_intexpr_compare:w #1=\intexpr_eval:w #2 \intexpr_eval_end: 
  \prg_return_false: \else: \prg_return_true: \fi:
}
%    \end{macrocode}
% Less than and greater than are also straight forward.
%    \begin{macrocode}
\cs_set:cpn {intexpr_compare_<:w} #1<#2\q_nil{
  \if_intexpr_compare:w #1<\intexpr_eval:w #2 \intexpr_eval_end: 
  \prg_return_true: \else: \prg_return_false: \fi:
}
\cs_set:cpn {intexpr_compare_>:w} #1>#2\q_nil{
  \if_intexpr_compare:w #1>\intexpr_eval:w #2 \intexpr_eval_end:
  \prg_return_true: \else: \prg_return_false: \fi:
}
%    \end{macrocode}
% The less than or equal operation is just the opposite of the greater
% than operation. Vice versa for less than or equal.
%    \begin{macrocode}
\cs_set:cpn {intexpr_compare_<=:w} #1<=#2\q_nil{
  \if_intexpr_compare:w #1>\intexpr_eval:w #2 \intexpr_eval_end: 
  \prg_return_false: \else: \prg_return_true: \fi:
}
\cs_set:cpn {intexpr_compare_>=:w} #1>=#2\q_nil{
  \if_intexpr_compare:w #1<\intexpr_eval:w #2 \intexpr_eval_end:
  \prg_return_false: \else: \prg_return_true: \fi:
}
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\intexpr_compare_p:nNn}
% \begin{macro}[TF]{\intexpr_compare:nNn}
% More efficient but less natural in typing.
%    \begin{macrocode}
\prg_set_conditional:Npnn \intexpr_compare:nNn #1#2#3{p,TF,T,F}{
  \if_intexpr_compare:w \intexpr_eval:w #1 #2 \intexpr_eval:w #3
  \intexpr_eval_end:
  \prg_return_true: \else: \prg_return_false: \fi:
}
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
%
% \begin{macro}{\intexpr_max:nn}
% \begin{macro}{\intexpr_min:nn}
% \begin{macro}{\intexpr_abs:n}
% Functions for $\min$, $\max$, and absolute value.
%    \begin{macrocode}
\cs_set:Npn \intexpr_abs:n #1{
  \intexpr_value:w 
  \if_intexpr_compare:w \intexpr_eval:w #1<\c_zero 
    -
  \fi:
  \intexpr_eval:w #1\intexpr_eval_end:
}
\cs_set:Npn \intexpr_max:nn #1#2{
  \intexpr_value:w \intexpr_eval:w 
    \if_intexpr_compare:w 
      \intexpr_eval:w #1>\intexpr_eval:w #2\intexpr_eval_end: 
      #1
    \else:
      #2
    \fi:
  \intexpr_eval_end:
}
\cs_set:Npn \intexpr_min:nn #1#2{
  \intexpr_value:w \intexpr_eval:w 
    \if_intexpr_compare:w 
      \intexpr_eval:w #1<\intexpr_eval:w #2\intexpr_eval_end: 
      #1
    \else:
      #2
    \fi:
  \intexpr_eval_end:
}
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
%
%
% \begin{macro}{\intexpr_div_truncate:nn}
% \begin{macro}{\intexpr_div_round:nn}
% \begin{macro}{\intexpr_mod:nn}
% As "\intexpr_eval:w" rounds the result of a division we also
% provide a version that truncates the result.
%    \begin{macrocode}
%    \end{macrocode}
%    Initial version didn't work correctly with e\TeX's implementation.    
%    \begin{macrocode}
%\cs_set:Npn \intexpr_div_truncate_raw:nn #1#2 {
%  \intexpr_eval:n{ (2*#1 - #2) / (2* #2) }
%}
%    \end{macrocode}
%    New version by Heiko:
%    \begin{macrocode}
\cs_set:Npn \intexpr_div_truncate:nn #1#2 {
  \intexpr_value:w \intexpr_eval:w
    \if_intexpr_compare:w \intexpr_eval:w #1 = \c_zero
      0
    \else:
      (#1
      \if_intexpr_compare:w \intexpr_eval:w #1 < \c_zero
        \if_intexpr_compare:w \intexpr_eval:w #2 < \c_zero
          -( #2 +
        \else:   
          +( #2 -
        \fi:
      \else:
        \if_intexpr_compare:w \intexpr_eval:w #2 < \c_zero
          +( #2 + 
        \else:   
          -( #2 -
        \fi:
      \fi:  
      1)/2)
    \fi:
    /(#2)
  \intexpr_eval_end:  
}
%    \end{macrocode}
% For the sake of completeness:
%    \begin{macrocode}
\cs_set:Npn \intexpr_div_round:nn #1#2 {\intexpr_eval:n{(#1)/(#2)}}
%    \end{macrocode}
% Finally there's the modulus operation.
%    \begin{macrocode}
\cs_set:Npn \intexpr_mod:nn #1#2 {
  \intexpr_value:w 
    \intexpr_eval:w  
    #1 - \intexpr_div_truncate:nn {#1}{#2} * (#2) 
    \intexpr_eval_end:
}
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\intexpr_if_odd_p:n}
% \begin{macro}[TF]{\intexpr_if_odd:n}
% \begin{macro}{\intexpr_if_even_p:n}
% \begin{macro}[TF]{\intexpr_if_even:n}
% A predicate function.
%    \begin{macrocode}
\prg_set_conditional:Npnn \intexpr_if_odd:n #1 {p,TF,T,F} {
  \if_intexpr_odd:w \intexpr_eval:w #1\intexpr_eval_end:
    \prg_return_true: \else: \prg_return_false: \fi:
}
\prg_set_conditional:Npnn \intexpr_if_even:n #1 {p,TF,T,F} {
  \if_intexpr_odd:w \intexpr_eval:w #1\intexpr_eval_end:
    \prg_return_false: \else: \prg_return_true: \fi:
}
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\intexpr_while_do:nn}
% \begin{macro}{\intexpr_until_do:nn}
% \begin{macro}{\intexpr_do_while:nn}
% \begin{macro}{\intexpr_do_until:nn}
%  These are quite easy given the above functions. The "while" versions
%  test first and then execute the body. The "do_while" does it the
%  other way round. 
%    \begin{macrocode}
\cs_set:Npn \intexpr_while_do:nn #1#2{
  \intexpr_compare:nT {#1}{#2 \intexpr_while_do:nn {#1}{#2}}
}
\cs_set:Npn \intexpr_until_do:nn #1#2{
  \intexpr_compare:nF {#1}{#2 \intexpr_until_do:nn {#1}{#2}}
}
\cs_set:Npn \intexpr_do_while:nn #1#2{
  #2 \intexpr_compare:nT {#1}{\intexpr_do_while:nNnn {#1}{#2}}
}
\cs_set:Npn \intexpr_do_until:nn #1#2{
  #2 \intexpr_compare:nF {#1}{\intexpr_do_until:nn {#1}{#2}}
}
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\intexpr_while_do:nNnn}
% \begin{macro}{\intexpr_until_do:nNnn}
% \begin{macro}{\intexpr_do_while:nNnn}
% \begin{macro}{\intexpr_do_until:nNnn}
%  As above but not using the more natural syntax. 
%    \begin{macrocode}
\cs_set:Npn \intexpr_while_do:nNnn #1#2#3#4{
  \intexpr_compare:nNnT {#1}#2{#3}{#4 \intexpr_while_do:nNnn {#1}#2{#3}{#4}}
}
\cs_set:Npn \intexpr_until_do:nNnn #1#2#3#4{
  \intexpr_compare:nNnF {#1}#2{#3}{#4 \intexpr_until_do:nNnn {#1}#2{#3}{#4}}
}
\cs_set:Npn \intexpr_do_while:nNnn #1#2#3#4{
  #4 \intexpr_compare:nNnT {#1}#2{#3}{\intexpr_do_while:nNnn {#1}#2{#3}{#4}}
}
\cs_set:Npn \intexpr_do_until:nNnn #1#2#3#4{
  #4 \intexpr_compare:nNnF {#1}#2{#3}{\intexpr_do_until:nNnn {#1}#2{#3}{#4}}
}
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
%
%    \begin{macrocode}
%</initex|package>
%    \end{macrocode}
%
% \end{implementation}
% \PrintIndex
%
% \endinput
