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