% Copyright 2014-2022, Alexander Shibakov
% This file is part of SPLinT
%
% SPLinT is free software: you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
% the Free Software Foundation, either version 3 of the License, or
% (at your option) any later version.
%
% SPLinT is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
% GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with SPLinT.  If not, see <http://www.gnu.org/licenses/>.

% a minimum of expandable arithmetic to implement a few macros in yyparse.sty and flex.sty
% the goal of these macros was not implementing a complete
% integer arithmetic but rather providing the minimal functionality
% where such arithmetic is required.
% there are a few instances in which the utility of such arithmetic is
% beneficial:
% o whenever an `expession macro' should behave like a number (i.e. be
%   useful in a \number context); see \YYSTART implementation for an
%   example 
% o whenever the use of a register is to be avoided in iterative
%   macros and replaced by a `tail parameter' (see \yyless for a hint
%   of such a use)
% o whenever \TeX's number size limitations are inadequate
%
% the last situation has not been a concern for this package while the
% other two were.
%
% `expandable' may have different meanings. in the context of
% arithmetic, expansion within \edef context, `prefix expansion' or
% \number or \romannumeral0 context expansion may all be valid
% targets. the preferred way seems to be the \romannumeral0
% interface. the disadvantage of this method is that each macro needs
% to produce a space at the end of its `expansion cycle', the
% advantage is the ability to carry the extension for arbitrarily
% large numbers (unlike, say, the \number interface). the macros below
% are implemented so that the \expandafter\expandafter `prefix'
% expansion and \number both work, even though internally, the
% \romannumeral0 approach is taken. this is done to present a cleaner
% use pattern to the consumer of the macros.
%
% for a complete implementation of expandable arithmetic (including
% floating point), see the corresponding parts of the
% \LaTeX\ project. it was decided against using that implementation to
% avoid creating dependencies.

% temporary definition, to avoid using reserved counters

\edef\xxcarry{\count3=\the\count3\count\z@\the\count\z@\count\@ne\the\count\@ne}

% digit extractor, used as part of several macros below.

\count\z@\z@
\bloop
    \edef\next{\def\csname digit\number\count\z@\endcsname##1\number\count\z@##2##3.{##2}}\next %
\ifnum9>\count\z@
    \advance\count\z@\@ne
\repeat

% multiplication tables:
% \xmultby?#1 expands into a pair ab which is a product of ? and #1

\count\z@\z@
\bloop{%
    \count\@ne\z@
    \let\next\empty
    \bloop
        \count3\count\z@
        \multiply\count3\count\@ne
        \edef\next{\next\number\count\@ne{\ifnum9<\count3 \else0\fi\number\count3}}%
    \ifnum9>\count\@ne
        \advance\count\@ne\@ne
    \repeat
    \edef\next{\def\csname xmultby\number\count\z@\endcsname##1{\noexpand\csname digit##1\noexpand\endcsname\next.}}\next
\ifnum9>\count\z@
    \advance\count\z@\@ne
}\repeat

% addition tables:
% \xaddto?#1 expands into a pair ab which is a sum of ? and #1

\count\z@\z@
\bloop{%
    \count\@ne\z@
    \let\next\empty
    \bloop
        \count3\count\z@
        \advance\count3\count\@ne
        \edef\next{\next\number\count\@ne{\ifnum9<\count3 \else0\fi\number\count3}}%
    \ifnum9>\count\@ne
        \advance\count\@ne\@ne
    \repeat
    \edef\next{\def\csname xaddto\number\count\z@\endcsname##1{\noexpand\csname digit##1\noexpand\endcsname\next.}}\next
\ifnum9>\count\z@
    \advance\count\z@\@ne
}\repeat

% division tables:
% \xdivby?#1 expands into #1 div ?

\count\z@\@ne
\bloop{%
    \count\@ne\z@
    \let\next\empty
    \bloop
        \count3\count\@ne
        \divide\count3\count\z@
        \edef\next{\next\number\count\@ne{\number\count3}}%
    \ifnum9>\count\@ne
        \advance\count\@ne\@ne
    \repeat
    \edef\next{\def\csname xdivby\number\count\z@\endcsname##1{\noexpand\csname digit##1\noexpand\endcsname\next.}}\next
\ifnum9>\count\z@
    \advance\count\z@\@ne
}\repeat

\xxcarry % restore registers

% #1\times #2 + #3

\def\xxcarry#1#2#3{%
    \expandafter\x@carry\number1\csname xmultby#1\endcsname#2#3%
}

% #1 is a bogus parameter, so that a leading 0 is not dropped by \number

\def\x@carry#1#2#3#4{%
    \expandafter\x@@arry\number1\csname xaddto#3\endcsname#4#2%
}

\def\x@@arry#1#2#3#4{%
    \ifnum#2>\z@\number\csname xaddto#2\endcsname#4\else#4\fi#3%
}

% most macros internally consume the digits from left to right.

\def\xreverse#1{%
    \romannumeral0\xr@verse{}#1.%
}

\def\xr@verse#1#2{%
    \if#2.%
        \yybreak{ #1}%
    \else
        \yybreak{\xr@verse{#2#1}}%
    \yycontinue
}

% multiplication by 0-9
% #1 is the number
% #2 is the digit
% expands to #1 * #2 in reverse digid order

\def\xmultiplybydigit#1#2{%
    \romannumeral0\xbydigit{#2}{0}{}#1.%
}

% #1 is the digit
% #2 is the carry
% #3 is the result
% #4 is the next digit of the big factor

\def\xbydigit#1#2#3#4{%
    \if#4.%
        \yybreak{\ifnum#2=\z@\xskiptofi{ #3}\else\xskiptofi{ #3#2}\fi}%
    \else
        \yybreak{\expandafter\xb@digit\number1#1\xxcarry#1#4#2 {#3}}%
    \yycontinue
}

% #1 is a bogus parameter (see above)
% #2 is the digit
% #3 is the carry
% #4 is the next digit of the result
% #5 is the result up to now

\def\xb@digit#1#2#3#4#5{%
    \xbydigit#2#3{#5#4}%
}

% a version of the macros above that perform the reversion to save an
% extra step

% #1 is the digit
% #2 is the carry
% #3 is the result
% #4 is the next digit of the big factor

\def\xbytigid#1#2#3#4{%
    \if#4.%
        \yybreak{\ifnum#2=\z@\xskiptofi{ #3}\else\xskiptofi{ #2#3}\fi}%
    \else
        \yybreak{\expandafter\xb@tigid\number1#1\xxcarry#1#4#2 {#3}}%
    \yycontinue
}

% #1 is a bogus parameter (see above)
% #2 is the digit
% #3 is the carry
% #4 is the next digit of the result
% #5 is the result up to now

\def\xb@tigid#1#2#3#4#5{%
    \xbytigid#2#3{#4#5}%
}

% similar to \xmultiply by digit above but produces the result in the
% usual digit order

\def\xsmallmultiple#1#2{%
    \romannumeral0\expandafter\xsm@llmultiple\expandafter{\romannumeral0\xr@verse{}#1.}#2%
}

\def\xsm@llmultiple#1#2{%
    \xbytigid{#2}{0}{}#1.%
}

% division by 2

\def\xdivbytwo#1{%
    \romannumeral0\expandafter\xdivbytw@\romannumeral0\xr@verse{}#1..%
}

\def\xdivbytw@#1#2{%
    \if#2.%
        \yybreak{\expandafter\space\number\csname xdivby2\endcsname#1}%
    \else
        \yybreak{\expandafter\xdivb@tw@\expandafter{\number\csname xdivby2\endcsname#1}#2}%
    \yycontinue
}

\def\xdivb@tw@#1{%
    \xbytigid{5}{#1}{}%
}

% increment by 1

\def\xincrement#1{%
    \romannumeral0\expandafter\x@ncrement\expandafter{\romannumeral0\xr@verse{}#1.}%
}

\def\x@ncrement#1{%
    \x@ncr@ment{1}{}#1.%
}

% #1 is the carry
% #2 is the result
% #3 is the next digit of the operand

\def\x@ncr@ment#1#2#3{%
    \if#3.%
        \yybreak{\ifnum#1=\z@\xskiptofi{ #2}\else\xskiptofi{ #1#2}\fi}%
    \else
        \yybreak{\ifnum#1=\z@\xskiptofi{\x@@cr@m@nt{#3#2}}\else
                             \xskiptofi{\expandafter\x@ncr@m@nt\number1\csname xaddto#1\endcsname#3{#2}}\fi}%
    \yycontinue
}

\def\x@ncr@m@nt#1#2#3#4{%
    \x@ncr@ment#2{#3#4}%
}

\def\x@@cr@m@nt#1#2.{%
    \xr@verse{}#2.#1%
}

% decimal complements table

\def\xcplof#1{\ifcase#1 \or9\or8\or7\or6\or5\or4\or3\or2\or1\fi}

% single digit decrement by 1 table

\def\xdecof#1{\ifcase#1 \or0\or1\or2\or3\or4\or5\or6\or7\or8\fi}

% decrement by 1

\def\xdecrement#1{%
    \romannumeral0\expandafter\xd@crement\expandafter{\romannumeral0\xr@verse{}#1.}%
}

\def\xd@crement#1{%
    \xd@cr@ment1{}#1.%
}

% #1 is the carry
% #2 is the result
% #3 is the next digit of the operand

\def\xd@cr@ment#1#2#3{%
    \if#3.%
        \yybreak{ -1}%
    \else
        \yybreak{\ifnum#1=\z@
                     \xskiptofi{\xde@@@m@nt{#3#2}}%
                 \else
                     \xskiptofi{%
                         \ifnum#3=\z@
                             \xskiptofi{\xd@cr@ment1{9#2}}%
                         \else
                             \xskiptofi{\expandafter\xde@@@m@nt\expandafter{\number\xdecof#3 #2}}%
                         \fi}%
                 \fi}%
    \yycontinue
}

\def\xd@cr@m@nt#1#2#3{%
    \xd@cr@ment#1{#2#3}%
}

\def\xde@@@m@nt#1#2.{%
    \xr@verse{}#2.#1%
}
