% 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 .
% 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%
}