# Plain TeX macro with float calculation

I am trying to take this TeX snippet and use it as the basis for a macro.

\centerline{\def\epsfsize#1#2{0.7#1} \epsfbox{1.01couet.eps}}

I am struggling with a bit that is required because I am actually redefining a macro that populates a rather large project. What I thought I could do is something like the following:

\def\myfig#1#2#3#4{\dimen1=#4 \divide\dimen1 by 1000
\centerline{\def\epsfsize#1#2{{#4}{#1}} \epsfbox{#3}}}

This is clearly incorrect, probably is several ways. I need to take argument #4 and divide it by 1000 to use as the scale (the 0.7 is the previous snippet). I understand dimen1 is not usable for dimensionless quantities but I can't find any documentation related to such a topic.

Note that the first two arguments would go unused for the time being.

Is there a good document that covers this?

I don't have 1.01couet.eps on my system. But every more recent TeX distribution has example-image-a.eps.

Therefore in the code-snippets below I will use the latter. ;-)

If I got you right, \myfig's fourth argument denotes whatsoever factor.
That factor shall be divided by 1000(decimal).
The result thereof shall be passed as scale-factor into the definition of \epsfsize?

You can do the calculation by means of dimensions. The point is:

\the\dimension1 yields the value held in dimension-register 1 based on the unit pt.

E.g., \the\dimension130.74pt.

Therefore do the calculation in terns of pt, and when it comes to using the result not as dimension but as number, strip off the phrase pt.

The results will not be very precise with this method of calculating.

Probably one of the packages fp or pgf (pgf's mathematical engine) is of interest to you.

Does the snippet below provide more or less correct scale-factors for \epsfsize ?

\input epsf.tex

\long\def\PassFirstToSecond#1#2{#2{#1}}%
\long\def\firstoftwo#1#2{#1}%
\long\def\secondoftwo#1#2{#2}%

\begingroup
\catcode P=12  %
\catcode T=12  %
\lowercase{%
\def\x{%
\def\RomannumeralDrivenRempt##1.##2PT{%
0\ifnum##2>0 \expandafter\firstoftwo\else\expandafter\secondoftwo\fi
{ ##1.##2}{ ##1}%
}%
}%
}%
\expandafter\endgroup\x%
\def\RomannumeralDrivenStrippt{\expandafter\RomannumeralDrivenRempt\the}%

\def\myfig#1#2#3#4{%
\begingroup
\dimen1=#4pt %
\dimen1=.001\dimen1 %
\expandafter\endgroup
\expandafter\centerline\expandafter{%
\expandafter\PassFirstToSecond\expandafter{%
\romannumeral\RomannumeralDrivenStrippt\dimen1 ##1%
}{\def\epsfsize##1##2}%
%%%
\show\epsfsize
%%%
\epsfbox{#3}%
}%
}%

\myfig{Unused 1}{Unused 2}{example-image-a.eps}{1000}

\myfig{Unused 1}{Unused 2}{example-image-a.eps}{700}

\myfig{Unused 1}{Unused 2}{example-image-a.eps}{200}

\myfig{Unused 1}{Unused 2}{example-image-a.eps}{40}

\bye

Here is the same code with a bit of explanation:

I assume this is where \epsfsize and \epsfbox come from:

\input epsf.tex

Put the first argument nested in braces behind the second argument—this way the tokens that form the first argument can be turned into arguments of the tokens that form the second argument:

\long\def\PassFirstToSecond#1#2{#2{#1}}%

Select the first of two arguments:

\long\def\firstoftwo#1#2{#1}%

Select the second of two arguments:

\long\def\secondoftwo#1#2{#2}%

Above I wrote: "...do the calculation in terns of pt, and when it comes to using the result not as dimension but as number, strip off the phrase pt". The problem is that with \the\dimen130.74pt the character tokens that form the phrase pt will not be of category-code 11(letter) but of category-code 12(other). So we need to get p of category-code-12 and t of category-code-12 into the code while also having these characters available in category-code 11 so they can be used within macro-names. So within a group temporarily change the category-codes of the uppercase-variants of these characters to 12. From these uppercase-variants you get the lowercase-variants in category-code 12 via \lowercase.

\begingroup
\catcode P=12  %
\catcode T=12  %
\lowercase{%
\def\x{%
\def\RomannumeralDrivenRempt##1.##2PT{%
0\ifnum##2>0 \expandafter\firstoftwo\else\expandafter\secondoftwo\fi
{ ##1.##2}{ ##1}%
}%
}%
}%
\expandafter\endgroup\x%

With the above the definition of \x will be

\def\x{%
\def\RomannumeralDrivenRempt##1.##2pt{%
0\ifnum##2>0 \expandafter\firstoftwo\else\expandafter\secondoftwo\fi
{ ##1.##2}{ ##1}%
}%
}%

, but the characters pt behind ##2 that delimit ##2 will be of category-code 12(other).

Therefore after expanding \x the definition of \RomannumeralDrivenRempt will be

\def\RomannumeralDrivenRempt#1.#2pt{%
0\ifnum#2>0 \expandafter\firstoftwo\else\expandafter\secondoftwo\fi
{ #1.#2}{ #1}%
}%

, with the characters pt behind #2 that delimit #2 of category-code 12(other). (As \x is defined inside the group, it needs to be expanded before ending the group, but in a way where the tokens delivered by \x appear behind the token \endgroup that ends the group. That's what \expandafter in \expandafter\endgroup\x is for.)

At first glimpse the definition looks weird. But if \RomannumeralDrivenRempt is preceded by \romanumeral and trailed by something like 400.23pt, you get the following:

\romannumeral\RomannumeralDrivenRempt400.23pt

This in turn yields:

Step 1:

% romannumeral-expansion in progress
\RomannumeralDrivenRempt400.23pt

Step 2:

% romannumeral-expansion in progress
0\ifnum23>0 \expandafter\firstoftwo\else\expandafter\secondoftwo\fi
{ 400.23}{ 400}%

Step 3:

% romannumeral-expansion in progress
% \romannumeral finds the digit 0 and keeps searching for more digits
% or a space-token that terminates the number and gets discarded.
\ifnum23>0 \expandafter\firstoftwo\else\expandafter\secondoftwo\fi
{ 400.23}{ 400}%

Step 4: The \ifnum-comparison yields the "true" branch:

% romannumeral-expansion in progress
% \romannumeral found the digit 0 and keeps searching for more digits
% or a space-token that terminates the number and gets discarded.
\expandafter\firstoftwo\else\expandafter\secondoftwo\fi
{ 400.23}{ 400}%

Step 5: \expandafter "hits" the else-branch and the else-branch gets removed:

% romannumeral-expansion in progress
% \romannumeral found the digit 0 and keeps searching for more digits
% or a space-token that terminates the number and gets discarded.
\firstoftwo
{ 400.23}{ 400}%

Step 6: \firstoftwo fetches the first argument:

% romannumeral-expansion in progress
% \romannumeral found the digit 0 and keeps searching for more digits
% or a space-token that terminates the number and gets discarded.
<space token>400.23

Step 7: Now \romannumeral "finds" the space-token. The space-token is taken for the terminator of the digit-sequence which forms the number which \romannumeral shall convert to roman notation. That terminator gets discarded and the digit-sequence that \romannumeral shall take for the number to convert consists only of the digit 0 while 0 is not a positive number while \romannumeral handles non-positive numbers as follows: It just swallows them without delivering any token in return:

% romannumeral-expansion done. \romannumeral found the non-positive
% number 0 and silently swallowed it without delivering any token
% in return:
400.23

Now let's continue with the code:

Above I wrote: "But if \RomannumeralDrivenRempt is preceded by \romanumeral and trailed by something like 400.23pt, you get the following:..." So a mechanism is needed which provides that trailing phrase:

\def\RomannumeralDrivenStrippt{\expandafter\RomannumeralDrivenRempt\the}%

(With the definition above

\romannumeral\RomannumeralDrivenStrippt\dimen1

yields:

Step 1:

%\romannumeral-expansion in progress
\RomannumeralDrivenStrippt\dimen1

Step 2:

%\romannumeral-expansion in progress
\expandafter\RomannumeralDrivenRempt\the\dimen1

Step 3: \expandafter "hits" \the

%\romannumeral-expansion in progress
\RomannumeralDrivenRempt400.23pt

This is step 1 of the expansion-chain of \RomannumeralDrivenRempt.

)

Now let's continue with the code:

\def\myfig#1#2#3#4{%
\begingroup
\dimen1=#4pt %
\dimen1=.001\dimen1 %
\expandafter\endgroup
\expandafter\centerline\expandafter{%
\expandafter\PassFirstToSecond\expandafter{%
\romannumeral\RomannumeralDrivenStrippt\dimen1 ##1%
}{\def\epsfsize##1##2}%
%%%
\show\epsfsize
%%%
\epsfbox{#3}%
}%
}%

\myfig{Unused 1}{Unused 2}{example-image-a.eps}{1000}

\myfig{Unused 1}{Unused 2}{example-image-a.eps}{700}

\myfig{Unused 1}{Unused 2}{example-image-a.eps}{200}

\myfig{Unused 1}{Unused 2}{example-image-a.eps}{40}

\bye

Let's exhibit the expansion-chain with

\myfig{Unused 1}{Unused 2}{example-image-a.eps}{700}

Step 1:

\begingroup
\dimen1=700pt %
\dimen1=.001\dimen1 %
\expandafter\endgroup
\expandafter\centerline\expandafter{%
\expandafter\PassFirstToSecond\expandafter{%
\romannumeral\RomannumeralDrivenStrippt\dimen1 ##1%
}{\def\epsfsize##1##2}%
%%%
\show\epsfsize
%%%
\epsfbox{example-image-a.eps}%
}%

Step 2: Inside the group perform temporary assignments to \dimen1 and do "\expandafter-hopping" in order to get the tokens that form the expansion of \romannumeral\RomannumeralDrivenStrippt\dimen1 as explained above behind the token \endgroup which closes the group:

\begingroup
\dimen1=700pt %
\dimen1=.001\dimen1 %
\endgroup
\centerline{%
\PassFirstToSecond{%
.7##1%
}{\def\epsfsize##1##2}%
%%%
\show\epsfsize
%%%
\epsfbox{example-image-a.eps}%
}%

The things inside the group reach TeX's stomach and get digested. The interesting remainder is:

\centerline{%
\PassFirstToSecond{%
.7##1%
}{\def\epsfsize##1##2}%
%%%
\show\epsfsize
%%%
\epsfbox{example-image-a.eps}%
}%

Step 3: Due to \PassFirstToSecond this is something like:

\centerline{%
\def\epsfsize##1##2{.7##1}%
%%%
\show\epsfsize
%%%
\epsfbox{example-image-a.eps}%
}%
• Thank you, thank you, thank you!! I think you understand question exactly. I will also look into fp! – Kevin Dec 22 '19 at 22:08
• @Kevin There's also xfp (which is a wrapper around the LaTeX3 FPU). See a comparison here. – Phelype Oleinik Dec 23 '19 at 14:42
• OK. This is useful and very interesting to me. While helping with this plain TeX project, I have become much more interested in plain TeX myself. I am still trying to fully understand the details of Ulrich's macro and I think it is something that I would like to become more skillful. Is there a good resource for plain TeX macros? I have the TeXBook on the way but, perhaps, there is something just focussed on macro "tips". – Kevin Dec 23 '19 at 15:51
• @Kevin I added some explanation to the code. I hope this helps understanding how things work... – Ulrich Diez Dec 23 '19 at 21:23
• – Ulrich Diez Dec 23 '19 at 21:38