%%% %%% File: mf-revu.tex %%% %%% mfpic 0.2.10.1 alfa Thu 18 Jan 1996 %%% \magnification=\magstep1 % heading macros \newskip\myskip\myskip=10pt plus 1pt \def\doskip{\vskip\myskip} \long\def\head#1{\doskip\noindent $\bullet$ {\it #1} \par\doskip\nobreak} \long\def\subhead#1{\doskip {\sl #1} \par\doskip\nobreak} % abbreviations \def\LaTeX{{\rm L\raise.42ex\hbox{\kern-.3em a}\kern-.15em\TeX}} \font\manual=logo10 % may want to use manfnt here instead \def\MF{{\manual META}\-{\manual FONT}} \def\PS{{\rm Post}\-{\rm Script}} \def\texmacro#1{{\tt\char\escapechar #1}} % verbatim text -- extracted from The TeXbook, pages 380--381. \def\verbatim{\tt \def\par{\leavevmode\endgraf} \obeylines \obeyspaces} {\obeyspaces\global\let =\ } \centerline{\bf A Review of \MF{} Programming} \centerline{Geoffrey Tobin ({\tt G.Tobin@latrobe.edu.au}) Thu 18 Jan 1996} The best reference for \MF{} programming is undoubtedly Professor Donald E.~Knuth's {\it The \MF{}book}, first published by Addison-Wesley and copyrighted by the American Mathematical Society in 1986, ISBN 0-201-13445-4. However, this document gives reminders of some facets of \MF{}. \head{Types} \MF{} has nine ($9$) types of expression: {\tt boolean}, {\tt numeric}, {\tt pair}, {\tt path}, {\tt pen}, {\tt picture}, {\tt string}, {\tt transform}, and {\it vacuous}. The first eight ($8$) are {\it named} types; their names can be used to declare variables (for example, {\tt string surname;}), or to test the type of a variable or expression (as in {\tt message "x is " \& if pair x: "indeed" else: "not" fi \& " a pair";}). Every undeclared \MF{} variable is {\tt numeric}. Statements can be treated as expressions of the {\it vacuous} type. Expressions of {\tt boolean} type are either {\tt true} or {\tt false}, whereas {\it vacuous} expressions have only one possible value. The allowed values of all the types, and the range of expressions available in \MF{}, are described in {\it The \MF{}book}. \head{Groups} A {\it group} is an {\it compound} expression of the form {\tt begingroup A; B; C; D endgroup} which may contain several statements; its value is that of its last expression, so {\tt begingroup message "hello"; 123.45 endgroup} has the value of $123.45$, which is {\tt numeric}. If the group is empty, or if its last item is a semicolon, then the group has the {\it vacuous} type. \head{Macros} {\it Macros} are the \MF{} equivalent of functions and procedures. There are two broad classes of macro: untyped ({\tt def}) and typed ({\tt vardef}). Typed macros are permitted to have the {\it vacuous} type: an example is {\tt vardef fred = message "I am called Fred"; enddef;}\ . In fact, {\tt vardef A = B enddef;} is effectively a shorthand for {\tt def A = begingroup B endgroup enddef;}\ . \head{Numerics} \subhead{\MF{} Numeric Operations} The arithmetic operators {\tt +}, {\tt -}, {\tt *}, {\tt /} are primitives in \MF{}. So are Pythagorean addition ({\tt ++}) and subtraction ({\tt +-+}): $x ++ y = \sqrt {x^2 + y^2}$ and $x +-+ y = \sqrt {x^2 - y^2}$. Plain \MF{} defines exponentiation ({\tt **}), remainder ({\tt mod}) and integer division ({\tt div}). \subhead{\MF{} Numeric Relations} Numeric expressions can be compared: relations include equality, ({\tt =}), and inequalities ({\tt <>}, {\tt >}, {\tt <}, {\tt >=}, {\tt <=}). \subhead{\MF{} Numeric Functions} \MF{} has some useful {\tt numeric} functions built-in. These include: length, sqrt, sind, cosd, mlog, mexp, floor, angle, uniformdeviate, normaldeviate. {\bf length $x$} is the absolute value of $x$. {\bf sqrt $x$} is the square root of $x$. {\bf sind $x$} is the sine of $x$ degrees. {\bf cosd $x$} is the cosine of $x$ degrees. {\bf angle $(x, y)$} is the arctangent of $y/x$. {\bf mlog $x$} is $256 \hbox{\tt ln} x$, where {\tt ln} is the logarithm to the base $e$. {\bf mexp $x$} is $e^{x/256}$. {\bf floor $x$} is the largest integer less than or equal to $x$. {\bf uniformdeviate $x$} is a uniformly distributed random number between $0$ and $x$. {\bf normaldeviate} is a normally distributed random number with mean $0$ and standard deviation $1$. The random number generators can be restarted at a given stage by assigning a {\tt numeric} value to the primitive internal variable {\bf randomseed}. Plain \MF{} defines {\bf ceiling}, {\bf abs} (same as {\bf length}), {\bf round}, {\bf min} and {\bf max}, among other functions. \head{Pairs} Subsequently, we often speak of {\it points} in the graphical sense. These are represented in \MF{} by values of type {\tt pair}. Constants of type {\tt pair} have the form $(x, y)$, where $x$ and $y$ are both {\tt numeric} constants. A variable $p$ of type {\tt pair} is equal to the {\tt pair} expression ({\tt xpart} $p$, {\tt ypart} $p$). \head{Paths} A {\tt path} represents a type of continuous curve called a {\bf B\'ezier}, which is comprised of a chain of {\bf segments}. Each segment has a shape determined by four {\bf control points}. Two of the control points, the {\it key} points, are the segment's endpoints; often we let \MF{} determine the other two, as in the {\tt path} expression $p_1..p_2..p_3$, which has two segments, from $p_1$ to $p_2$, and from $p_2$ to $p_3$. \head{Pens} Pens are a distinctive feature of \MF{}, whereby quite refined figures can be drawn. Pens are filled convex shapes that are moved along {\tt path}s, to alter {\tt picture} pixel values in often complicated ways. Two pens are initially present in MF{}, {\tt nullpen} and {\tt pencircle}. Since {\tt nullpen} is the single point $(0,0)$, which contains no pixels, it cannot be seen, so it can be used for filling a region without fuzzing its boundary. By contrast, {\tt pencircle} is circular, with the points $(\pm0.5, 0)$ and $(0, \pm0.5)$ on its circumference. Other pens are constructed as convex polygons via {\tt makepen $c$}, where $c$ is a closed {\tt path}; the key points of $c$ become the vertices of the pen. Now, {\tt pencircle} and {\tt makepen $c$} are called {\it future} pens. They are continuous, whereas pictures are discrete, so pens, like pairs and paths, must be {\it rendered} discrete before being applied to a picture. By contrast, {\tt nullpen}, all {\tt pen} variables, and any pen expression in parentheses, are already {\it discrete} pens. {\it Future} pens can be transformed by scaling, translating, and so on, just as pairs and paths can; but {\it discrete} pens cannot. An example of an elliptical future pen is {\tt pencircle xscaled 30 yscaled 20}, the discrete pen for which is illustrated on page 148 of {\it The \MF{}book}. \head{Pictures} \MF {\tt picture}s contain pixels arranged as a regular grid of squares. One of the pixels has as its boundary the {\it unit square}, which is the {\tt path} $(0,0)--(0,1)--(1,1)-(1,0)--cycle$. Pictures are built up from the {\tt nullpicture}, which has all pixels zero ($0$), using {\tt addto}, and their pixels are trimmed using {\tt cull}. Picture variables can be assigned: $v := W;$ where $v$ is a {\tt picture} variable, and $W$ is a {\tt picture} expression such as $u + w$, $u - w$, $+u$, $-u$, or combinations of these. Picture $v$ can have picture $w$ added to it by {\tt addto $v$ also $w$}, which {\it The MF{}book, page 118} explains is faster and uses less memory than {\tt $v := v + w$} but is otherwise the same. The meaning of $v + w$, for example, is a picture in which each pixel is the sum of the two pixels that occupy the same position in pictures $v$ and $w$ respectively. The effects on pixel values of filling and drawing are much less predictable, and depend greatly on which {\tt pen} is used. Filling a {\it closed} path $c$ in a picture $v$ uses {\tt addto $v$ contour $c$ {\it }}, Drawing the outline of a path $f$ uses {\tt addto $v$ doublepath $c$ {\it }}. A {\it } can be empty, or it can be one or both of the phrases {\tt withpen {\it }} and {\tt withweight {\it }}. By choosing different pens, drawing is refined, as in calligraphy. Weights are weighting factors for pixels. To change all pixels in {\tt picture} variable $v$ that have values between $2$ and $4$ (inclusive) into $-5$, and all other pixels to zero, use: {\tt cull $v$ keeping $(2,4)$ withweight $-5$}. To zero all pixels with values between $-3$ and $1$ (inclusive), and to change all other pixels into $2$, use: {\tt cull $v$ dropping $(-3,1)$ withweight $2$}, If the {\tt withweight} phrase is omitted, then the surviving pixels have value one ($1$). {\it Beware} of attempting to change zero-valued pixels to nonzero, as zero-valued pixels extend to infinity in all directions. \head{Transforms} Affine transforms are the natural transformations of Euclidean geometry: the linear transformations augmented by translation. In two dimensions, transforms are completely specified by their action on three non-collinear points in the plane. If $T$ is a {\tt transform}, and $p$ is a pair, then $T$ maps $p$ onto this {\tt pair}: $p$ {\tt transformed} $T$. Thus \MF{} can construct any affine transform: for example, plain \MF{} defines the {\bf identity} transform. Plain \MF{} also defines a macro named {\bf inverse} such that {\bf inverse $T$ transformed $T$ $=$ identity}. Each transform $T$ has six components, and can be expressed as a linear transformation followed by a translation. The translation components of $T$ are {\tt xpart $T$} and {\tt ypart $T$}, and the four linear components are {\tt xxpart $T$}, {\tt xypart $T$}, {\tt yxpart $T$} and {\tt yypart $T$}. Employing the obvious notation, $T$ is applied as: $$ \left( \matrix{t_x \cr t_y} \left| \vphantom{\matrix{t_xy \cr t_yy}} \right. \matrix{ t_{xx} & t_{yx} \cr t_{xy} & t_{yy}} \right) \pmatrix{x \cr y} = \pmatrix{t_x + t_{xx} x + t_{xy} y \cr t_y + t_{yx} x + t_{yy} y} $$ \MF{} also provides seven primitive transforms, listed on page 141 of {\it The \MF{}book}: \halign {\indent#\hfil&\quad#\hfil\cr $(x,y)$ {\tt shifted} $(a,b)$ & $ = (x+a, y+b) $ \cr $(x,y)$ {\tt scaled} $s$ & $ = s (x, y) $ \cr $(x,y)$ {\tt xscaled} $s$ & $ = (sx, y) $ \cr $(x,y)$ {\tt yscaled} $s$ & $ = (x, sy) $ \cr $(x,y)$ {\tt slanted} $s$ & $ = (x,y) + s (y, 0) $ \cr $(x,y)$ {\tt rotated} $\theta$ & $ = (x \cos \theta - y \sin \theta, x \sin \theta + y \cos \theta) $ \cr $(x,y)$ {\tt zscaled} $(u,v)$ & $ = (xu - yv, xv + yu) $ \cr } These operations are taught in secondary school mathematics; for example, {\tt slanted} is skewing parallel to the X axis. Interpreting a pair as a complex number in Cartesian coordinates, {\tt zscaled} is complex multiplication. \head{Composite Variables} \MF{} allows {\it composite} variables --- homogeneous {\it arrays}, heterogeneous {\it suffixes}, and arbitrary combinations of those. One can declare composite variables, and test whether they {\it contain} a given structure. However, these are not fully-fledged types, since every expression has one of the nine {\it simple} types. For example, after declaring {\tt path p[];} of what type is {\tt p} ? It's {\tt numeric}! Moreover, \MF{} {\it lacks} pointers. It is not possible for a macro to return a value that has not one of the nine {\it simple} types. The allowed syntax {\tt vardef b[] = $\cdots$ enddef;} may suggest that this macro returns an array, but in fact {\tt b[3]} {\it expands} to the whole {\it replacement text} of the macro. Here is a macro that is useful for testing the type of a variable, suffix or expression: { \verbatim def type suffix x = message str x \& " is " \& if known x: "a known " else: "an unknown " fi \& if boolean x: "boolean" elseif numeric x: "numeric" elseif pair x: "pair" elseif path x: "path" elseif pen x: "pen" elseif picture x: "picture" elseif string x: "string" elseif transform x: "transform" else: "vacuous" fi; enddef; } \bye %%% %%% EOF %%%