{\MakeShortVerb{\"}

\noindent
The following pages contain some exercises that introduce the use of
\cmix{} in partial evaluation. To use the makefiles with the
exercises---which is strongly recommended---you need access to the GNU
"make" utility (called "gmake" here), to view the annotated source
programs you need access to a WWW-browser like Netscape, to run the C
interpreter example in Section~\ref{sec:CInterpreter} you need access
to the GNU "bison" and "flex" parser and lexer generator utilities,
and to view ray tracing online you need the SRGP, PTC or OpenGL
graphics library~\cite{SRGP,PTC,OpenGL}.


\tutorsection{Getting started}
\label{sec:GettingStarted}

To avoid confusion, each \cmix{} example resides in its own
subdirectory of the directory "$CMIXDIR/examples", where "$CMIXDIR" is
the directory on your server that \cmix{} resides in. We suggest you
start by making a copy of them in a working directory, in these
exercises we will assume your working directory is called
"~/cmix/exercises". On a UNIX system this can be done by typing
something like this (you type in the commands in
\UserTypes{boldface}): {\small
\begin{alltt}
[~] \UserTypes{mkdir -p  \~{}/cmix/exercises}
[~] \UserTypes{cp -R  \$CMIXDIR/examples/*   \~{}/cmix/exercises}
[~] \UserTypes{ls  \~{}/cmix/exercises}
ack        cint       matrix     printf
binsearch  fft        pow        turing
[~]
\end{alltt}}
\noindent
To try out your first example, type 
\UserTypes{cd \~{}/cmix/exercises/pow} to change to the "pow"
directory, and view 
the source file by typing \UserTypes{cat pow.c}: 
{\small
\begin{alltt}
[~] \textrm{\UserTypes{cd  \~{}/cmix/exercises/pow}}
[~/cmix/exercises/pow] \textrm{\UserTypes{cat pow.c}}
double pow(double x, int n)
\verb"{"
  double a = 1;
  while(n--) a *= x;
  return a;
\verb"}"
[~/cmix/exercises/pow]
\end{alltt}}
\noindent
The simplest way to process files with \cmix{} is by using a makefile.
Run your first \cmix{} example by typing \UserTypes{gmake}, producing
something like this:
{\small
\begin{alltt}
[~/cmix/exercises/pow] \UserTypes{gmake}
gcc -O3   -c pow-time.c -o pow-time.o
gcc -O3   -c pow.c -o pow.o
cmix -s -q -e 'goal: pow(?,\$1) producing ("pow_res")' pow.c \hfill\textcomment{(run \cmix{} to\ }
Info: Partially static structures turned off \hfill\textcomment{make the generating extension)}
gcc -I /usr/local/topps/mix/lib/cmix -L /usr/local/topps/mix/lib/cmix
    -o pow-gen pow-gen.c -lcmix \hfill\textcomment{(compile the generating extension)}
./pow-gen 15 | (gindent -br -ce || cat) > pow-res.c \hfill\textcomment{(run generating extension to\ }
gcc -O3   -c pow-res.c -o pow-res.o \hfill\textcomment{produce residual program)}
gcc -o pow-time  pow-time.o pow.o pow-res.o \hfill\textcomment{(link source \& residual program\ }
648 pow.o \hfill\textcomment{for timing purposes)}
609 pow-res.o
./pow-time 10000000 2 15 >> pow-time.txt
Timing source program...
Timing residual program...
Done.
head -8 pow-time.txt; tail -8 pow-time.txt
============================================================
Program pow.c on host embla, architecture hp700pa2ux10:
Compiler command is `gcc  -O3'
Input is `2 15'

Source   program size: 648 pow.o
Residual program size: 609 pow-res.o

Source   result: 32768.000000
Residual result: 32768.000000

                  User time       (System time   )
Source   program    3.68 seconds  (     0 seconds)
Residual program    1.33 seconds  (     0 seconds)
Speedup factor       2.8          (   1.0        )
============================================================
rm pow-gen pow-time.o pow-gen.c pow-res.o pow-time pow.o
[~/cmix/exercises/pow]
\end{alltt}}
\noindent
The makefile is set up as explained in the next section to call
\cmix{} for specializing the power function  to spectime "n"=15,
and then do some timing comparisons: The source program is  run
10000000 times with "x"=2 and "n"=15, and the residual program is run
10000000 times with "x"=2.

If you find the directory is filling up, you can remove automatically
generated files by typing \UserTypes{gmake clean}. This can also be
useful if you have adjusted some specialization parameters and you
want to make sure everything is recomputed.


\paragraph{Exercise:}

View the annotated source program that the \cmix{} analyses produce by
typing \UserTypes{cmixshow pow.ann}.  If your "$BROWSER" environment %$-match
variable is set up correctly (e.g.\ as ``"netscape"''), this will
start up a browser window, like the one shown in
Figure~\vref{fig:AnnotationBrowser}.%
\begin{figure}[htb]
  \begin{center}\leavevmode
  \hbox{\vrule\vbox{\hrule
      \hbox{\includegraphics[width=.6\textwidth]{bw-pow-ann}}}}
    \caption{The source code annotation browser}
    \label{fig:AnnotationBrowser}
  \end{center}
\end{figure}
Click on
$\vcenter{\hbox{\includegraphics[width=4cm]{selectvisible}}}$
and select which type of annotations, e.g. residual program parts, you
would like to see details about. These details will then appear in the
lower part of the browser when you click on a program construct. If
you re-specialize by invoking \cmix{} again, you can update the
browser window by clicking on the reload button.


\paragraph{Exercise:}

Print out the source and residual programs (source program: make sure
the top frame is selected by clicking somewhere in it, then click on
the print button in your browser, residual program: by using your
local command for printing ASCII files,
e.g.~\UserTypes{lpr pow-res.c}) and compare to see what \cmix{} has
reduced and unfolded.


\tutorsubsection{Doing it on your own}
\label{sec:DoingItOnYourOwn}

If you want to make your own example and run it through \cmix, we
suggest you create a new directory with makefiles etc.\ by
using the "pow" example directory as a template.


\tutorsection{Exercise: text formatting with \texttt{printf}}
\label{sec:Printf}

Change to the "printf" directory and take a look at the source file
"prntf.c"; it contains four functions: a function 
"mini_printf(fmt, values)" that handles a small subset of the
formatting of the standard 
C library function "printf", a function "putint(i)" for printing
integers, the power function "power(x, n)" and a goal function
"goal(x, n)" that acts as an entry point for \cmix.

The aim is to specialize away all operations on the formatting string
\verb+"Power = %d\n"+
and the spectime variable "n". This is set up in the top of
the makefile:
{\small
\begin{alltt}
#---- EXAMPLE SPECIFIC SECTION -------------------------------

SOURCEPROG      = prntf.c
GOALFUN         = goal
BINDTIMES       = (?,$$1)
TESTDATA        = 2 23
SPECTIMEDATA    = 23
REPEAT          = 100000
CFLAGS          = -O3
CMIXFLAGS       = -s -q

#---- END OF EXAMPLE SPECIFIC SECTION ------------------------
\end{alltt}}
\noindent
The binding times of the parameters to the "goal" function are given
by ``"(?,$$1)"'', indicating that the first parameter, "x", is
residual (unknown) and "n" is a spectime parameter given as argument
number~1 to the generating extension.  The example is specialized with
spectime data $"n" = 23$.

Try making the residual program by typing \UserTypes{gmake prntf-res.c} and
take a look at it---notice how the format string is now built into the
specialized "mini_printf" function.

The program "prntf-time.c" performs  timing and comparisons of the
source and residual programs. The first few lines look somewhat like
this:
{\small
\begin{alltt}
/**** EXAMPLE SPECIFIC SECTION ****************************/

#define ARGS 2
extern int goal(int x, int n);
extern int goal_res(int x);
int x; int n;
#define READARGS     x = atoi(argv[1]); n = atoi(argv[2])
#define CALLSOURCE   goal  (x, n)
#define CALLRESID    goal_res(x)
#define FORMATRESULT "%d"

/**** END OF EXAMPLE SPECIFIC SECTION *********************/
\end{alltt}}
\noindent
The C macro "ARGS" indicates how many arguments the source goal
function "goal" takes. This function is declared, along with the
specialized "goal_res" function. C Macro "READARGS" reads and converts
the arguments from the command line in usual C style, while
"CALLSOURCE" and "CALLRESID" perform the calls to the source and
residual functions. The result of each of these functions is
formatted using the "FORMATRESULT" string.

When the timing program "prntf-time" is run via the makefile, the
"TESTDATA" input from the makefile is passed, along with the "REPEAT"
value which indicates how many times the calls should be
repeated. This is to make sure that the running times are not too
short for timing purposes.


\paragraph{Exercise:}

Try making alterations and additions to the "prntf.c" program or the
top of the makefile, and then do \UserTypes{gmake timing} after each:
what happens if you add several calls to "mini_printf"? With different
spectime arguments?  With identical spectime arguments? Try also
getting an estimate of the speedup by typing \UserTypes{gmake
  timing}---speedups around 1 to 8 are usual for partial evaluation.


\tutorsection{Exercise: Binary search}
\label{sec:BinarySearch}

Given a sorted array of numbers, finding the index of some given number $a$
 can be done in logarithmic time by comparing
$a$ with an array element near the middle and continuing in this fashion with
either the upper or lower half of the array. Looking for $42$ in the
list $17,23,42,43,67,73,79,91$ can be done in 4 steps:

{\let\obox\underline
\newcommand{\cbox}[1]{\hbox to 0pt{\hss #1\hss}}
\newcommand{\Array}[1]{\bgroup\arraycolsep=1em
  \begin{array}{#1}\ArrayBody}
\newcommand{\ArrayBody}[9]{\cline{#9}
\cbox{#1}&\cbox{#2}&\cbox{#3}&\cbox{#4}&
\cbox{#5}&\cbox{#6}&\cbox{#7}&\cbox{#8}\\\cline{#9}\end{array}\egroup}

\newcommand{\Low}[3]{\cbox{%
    \raisebox{-1.2em}[0pt][0pt]{%
      $\mathop{\uparrow}\limits_{\mathit{low}=#1}$}}\cbox{#3}}
\[
\begin{array}{r@{\qquad}c}
\mathit{disp} = 8 &
\Array{|cccccccc|}{\Low{0}{8}{17}}{23}{42}{\obox{43}}{67}{73}{79}{91}{1-8}
\\[2.5em]
\mathit{disp} = 4 &
\Array{|cccc|cccc}{\Low{0}{4}{17}}{\obox{23}}{42}{43}{67}{73}{79}{91}{1-4}
\\[2.5em]
\mathit{disp} = 2 &
\Array{cc|cc|cccc}{17}{23}{\Low{2}{2}{\obox{42}}}{43}{67}{73}{79}{91}{3-4}
\\[2.5em]
\mathit{disp} = 1 &
\Array{cc|c|ccccc}{17}{23}{\Low{2}{1}{42}}{43}{67}{73}{79}{91}{3-3}
\\[2em]
\end{array}
\]}
At each step, $a$ is compared with the underlined element, the
displacement $\textit{disp}$ is halved, and the offset $\textit{low}$
is adjusted accordingly.

A function "binsearch(x, size, a)" that searches for "x" in an array
"a" of length "size" initialized to contain $[0, 1, 2, ..., "size"-1]$
can be found in the file "bsrch1.c" in the "binsearch" directory.
Try specializing and timing this function with spectime "size" = 512
by typing \UserTypes{gmake timing1} (this may take a while).\midrule

As you can see, the specialization has produced a speedup of around 4,
but at the cost of a residual program about 35 times the size of the
source program! Take a look at the residual program
("bsrch1-res.c"). Before you continue reading, consider the
following question: what makes it so huge? (Hint: what happens when
you change the spectime value 512?)\midrule

The problem is that the residual program contains one "if" statement
for each element in the array---a total of 512 in this case! This
kind of code explosion is often undesirable, and is a result of ``too
much'' specialization. This can be improved by instructing \cmix{} to
residualize some constructs that actually could be performed at
spectime. Given a function with a variable "y" that should be
residualized:
\begin{alltt}
int f(int x) \verb"{"
  int y;
  ...
\end{alltt}
this is done
by adding a "#pragma" to the source file like this:
\begin{alltt}
int f(int x) \verb"{"
#pragma cmix residual: f::y
  int y;
  ...
\end{alltt}
(This can also be specified in a separate ".cmx" file, cf.~the User
Manual.)


\paragraph{Exercise:}

Make a copy of "bsrch1.c", call it "bsrch2.c", and take a look
at the annotations by typing \UserTypes{cmixshow bsrch1.ann}.
Decide which variable, "disp" or "low", should be residualized, insert
the appropriate "#pragma" in the "bsrch2.c" file, and examine the
differences in code, speedup and code explosion by typing
\UserTypes{gmake timing1 timing2}. (A correct solution can be found in
"answr2.c").


\tutorsection{Exercise: Ackermann's function}
\label{sec:Ackermann}

In directory "ack" you will find a small program in "ack1.c" for
computing Ackermann's function:
\[
\mathit{Ack}(m,n) = \left\{
  \begin{array}{ll}
    n + 1, & \textnormal{ if } m = 0 \\
    \mathit{Ack}(m - 1, 1), & \textnormal{ if } m > 0 \land n = 0 \\
    \mathit{Ack}(m - 1, \mathit{Ack}(m, n - 1)), & \textnormal{ if } m
    > 0 \land n > 0
  \end{array}\right.
\]
Try specializing Ackermann's function for spectime $m = 3$ by typing
\UserTypes{gmake timing1}. The resulting program, "ack1-res.c" is a little
messy because it is machine-generated, but a tidy version of it can be
found in "ack1-tidy-res.c".

Note that there are three calls to functions where the arguments are
the constant 1 that have not been reduced. The reason is that \cmix{}
makes a \emph{monovariant} binding-time division: in all calls to
"ack", the second parameter must be residual (because it is so in
\emph{some} calls). Make a copy of file "ack1.c", call it "ack2.c",
and figure out a way to circumvent this problem by hand-rewriting the
program (a solution is given in "answr2.c"). Specialize it by
typing \UserTypes{gmake timing2}. A tidy version of the residual program
can be found in "ack2-tidy-res.c".


\tutorsection{Exercise: Turing machine}
\label{sec:TuringMachine}

In the "turing" directory you will find a small Turing machine
interpreter in file "turng1.c". The machine has an instruction pointer
$i$, a tape pointer $p$ and takes a list of
instructions. Initially, $p$ points to the first element of the  tape,
and the Turing machine handles these instructions:
\begin{center}
\begin{tabular}{lp{.7\textwidth}}
\textit{Left}    & move $p$ one step left on the tape, unless $p=0$ \\
\textit{Right}   & move $p$ one step right on the tape, unless
                   $p=\mathit{tapemax}$ \\
\textit{Write a} & write character $a$ at the current tape position \\
\textit{Goto i}  & let next instruction be instruction $i$ \\
\textit{If a goto i} & if the character at the current tape position
is equal to $a$, let the next instruction be $i$ \\
\textit{Stop}    & stop and return the part of the tape that starts at
the current tape position \\
\end{tabular}
\end{center}
The following Turing program that can be found in file "first0to1.t"
finds the first '0' on the tape, changes it into a '1', and returns
the rest of the tape, starting at this '1':
\begin{center}
\begin{tabular}{ll}
0 & \textit{If} '0' \textit{goto} 3 \\
1 & \textit{Right}\\
2 & \textit{Goto} 0\\
3 & \textit{Write} '1'\\
4 & \textit{Stop}\\
\end{tabular}
\end{center}
For instance, running this program on tape 110101 returns 1101.

The function called
 "loadAndRunTuring(char* filename," "char tape[]," "int tapelen)"
loads a Turing program from a file and then calls
another function "turing(char tape[]," "int tapelen)" that implements
the Turing machine.


\paragraph{Beginner's exercise:}

Specialize the turing interpreter in file "answr1.c" by
typing \UserTypes{gmake answer1}, then view the residual source program
"answr1-res.c" to see what can be produced.

Now try specializing the turing interpreter in file "turng1.c" by
typing \UserTypes{gmake}. Finally, look at the function
"turing(char tape[], int tapelen)" in both source files and explain
the different specialization results.


\paragraph{Advanced exercise:}

Try specializing the program with spectime instruction list
"instruction", instruction pointer "i", tape pointer "p", and residual
"tape" by typing \UserTypes{gmake}. What is the problem? Look at the
annotated program by typing \UserTypes{cmixshow turng1.ann}; what is
the reason for this problem? Solve it by inserting appropriate
"#pragma"s (a correct solution can be found in "answr1.c").
\midrule

The problem is \emph{infinite specialization:} \cmix{} does not know
the length of the tape at specialization time, so it generates
specialized code for all possible positions of the tape pointer---of
which there are infinitely many. By forcing the tape pointer to become
residual, this infinite specialization is avoided.

Take a look at the residual program;
note how well it resembles the Turing program! Only now it is in C
code, so we have in effect obtained a compilation of Turing code into
C code!


\paragraph{Slightly time-consuming exercise: code blowup}
What happens if you specialize with "tapelen" as a spectime constant of
500? This requires alterations in the makefile so that it reads
{\small
\begin{alltt}
#---- EXAMPLE SPECIFIC SECTION -------------------------------

SOURCEPROG      = turng.c
GOALFUN         = loadAndRunTuring
BINDTIMES       = ($$1,?,$$2)
TESTDATA-turng1 = first0to1.t "110101---" 500
SPECDATA-turng1 = first0to1.t 500
REPEAT          = 1000000
CFLAGS          = -O3
CMIXFLAGS       = -s -q
TESTDATA-turng2 = 3right1left.t "001000110---"
SPECDATA-turng2 = 3right1left.t
TESTDATA-answr1= $(TESTDATA-turng1)
SPECDATA-answr1= $(SPECDATA-turng1)
TESTDATA-answr2= $(TESTDATA-turng2)
SPECDATA-answr2= $(SPECDATA-turng2)

#---- END OF EXAMPLE SPECIFIC SECTION ------------------------
\end{alltt}}
\noindent
and file "turng-time.c" to read
{\small
\begin{alltt}
/**** EXAMPLE SPECIFIC SECTION ****************************/

#include "turng.h"
#define ARGS 3
extern char* turing(char[], int);
extern char* turing_res(char[], int);
char* tape; int tapelen;
#define READARGS     readTuringProgram(argv[1]); \verb"\"
                     tapelen = atoi(argv[3]); \verb"\"
                     tape = (char*)malloc(2 * tapelen * sizeof(char)+1);
#define CALLSOURCE   (strcpy(tape, argv[2]), turing    (tape, tapelen))
#define CALLRESID    (strcpy(tape, argv[2]), turing_res(tape, tapelen))
#define FORMATRESULT "%s"

/**** END OF EXAMPLE SPECIFIC SECTION *********************/
\end{alltt}}
\noindent
(Remember to remove any "residual: turing::p" directive.) What are
the speedup and code blowup factors like? What seems to be the best
binding time for tape pointer "p"?  \bigskip


\paragraph{Exciting, time-consuming exercise!}\hskip 0pt plus 1em

Make a copy of "turng1.c", calling it "turng2.c" and extend the Turing
machine by adding a new instruction \textit{ReadGoto} which reads a
digit $i$ off the tape and jumps to that instruction---a ``computed
goto.'' (A solution can be found in "answr2.c".) The following
Turing program, found in file "3right1left.t", uses the
\textit{ReadGoto} instruction to repeatedly go 3 steps right or 1 step
left according to whether the current symbol is '1' or '0', replacing
any '1's by '0' as it does so. When two '1's in a row are encountered,
it goes 3 steps left and stops.
\begin{center}
\begin{tabular}{ll@{\qquad}ll}
 0 & \textit{Goto} 6                   &  7 & \textit{Left}\\    
 1 & \textit{Right}                    &  8 & \textit{ReadGoto}\\
 2 & \textit{Right}                    &  9 & \textit{Left}\\    
 3 & \textit{Right}                    & 10 & \textit{Left}\\    
 4 & \textit{If} '1' \textit{goto} 9   & 11 & \textit{Left}\\    
 5 & \textit{ReadGoto}                 & 12 & \textit{Stop}\\    
 6 & \textit{Write} '1'\\
\end{tabular}
\end{center}
For instance, running this program on tape 001000110 returns 111110.
The modified interpreter can be specialized to this program by typing
\UserTypes{gmake timing2}---remember to set up the makefile and timing
program as they were originally if you have changed them in the
previous exercise.

Can you still specialize the Turing interpreter with spectime
instruction list?
\midrule

The present problem arises often in interpreters: the index of the
next (spectime) instruction depends on some residual data, yet we
\emph{know} that it can only be one of finitely many different
values. Can you think of a way of exploiting this \emph{bounded static
  variation} so that the instruction list can be specialized away?
\midrule

The solution is so often seen in partial evaluation that it has been
named \emph{The Trick}: when an assignment "s = d" of a residual value
"d" to a spectime variable "s" that can only evaluate to finitely many
different values must be performed, a switch statement is inserted in
the source program:
{\small
\begin{alltt}
  switch (d) \verb"{"
    0 : s = 0; break;
    1 : s = 1; break;
    \vdots
    \(n\) : s = \(n\); break;
  \verb"}"
\end{alltt}}


\tutorsection{Exercise: C interpreter}
\label{sec:CInterpreter}

In directory "cint" you will find a file "cint1" containing an
interpreter for a small subset of the C language: the interpreted
language includes functions, integer variables and constants, some
arithmetic operators, if- and while-statements.

This is an example of supplying some of the spectime input not on the
command line but in a text file.  This requires parsing, which is
performed by a parser generator generated parser that is not
specialized---instead it is linked into the generating extension as a
spectime function "readProg(char* filename)".

Try specializing the interpreter to
the power function defined in "power.c" by typing \UserTypes{gmake
  timing1}. Note the speedup factor, which is due to more or less
removing a complete layer of interpretation: all handling of the
syntax of "power.c" has disappeared from the residual program.

The residual program contains rather a lot of small
functions;  a slightly tidier version can be found in
"cint1-tidy-res.c". Try comparing programs: are there any
similarities between "power.c" and "cint1-tidy-res.c"? Between
"cint1.c" and "cint1-tidy-res.c"?

The evaluation of if-statements is missing. Make a copy of "cint1.c",
call it "cint2.c",  add the missing code, and specialize the
interpreter to the greatest common divisor function in "gcd.c" by
typing \UserTypes{gmake timing2} (a solution can be found in
"answr2.c").

\paragraph{Interesting but probably very time-consuming exercise!}
Currently, the interpreter can handle several function
\emph{definitions}, but not function \emph{calls}. Try extending the
interpreter, e.g.\ with function calls. Make sure that all syntax
handling is still done at specialization time.


\tutorsection{Exercise: Matrix operations}
\label{sec:MatrixOperations}

In the "matrix" directory you will find a program "mtrix1.c" that
contains the following matrix and vector operations for $M = 25$:
\begin{center}
\small\def\x{\times}
\newlength\tmpdim
\settowidth\tmpdim{\texttt{vector mulMatVec(matrix A, vector b);}}
\addtolength\tmpdim{-.95\textwidth}\addtolength\tmpdim{2\tabcolsep}
\noindent
\begin{tabular}{@{}lp{-\tmpdim}@{}}
\texttt{vector solve(matrix A, vector b);} &
Solve $Ax=b$ and return $x$ for $M\x M$ matrix $A$ and $M\x 1$ vectors
$x$ and $b$ \\
\texttt{vector mulMatVec(matrix A, vector b);} &
return $A  b$ for matrix $A$ and vector $b$ \\
\texttt{char* printMatrix(matrix A);} &
return a text representation of $A$ \\
\texttt{char* printVector(vector b);} &
similar to \texttt{printMatrix} \\
\texttt{matrix makeMatrix(unsigned int seed);} & \rightskip 0pt plus 4em
return a matrix with pseudo-random numbers deterministically generated
from \textit{seed} \\
\texttt{vector makeVector(unsigned int seed);} &
similar to \texttt{makeMatrix}\\
\end{tabular}
\end{center}\pagebreak[3]
At the bottom of the file you will find the goal function:
\begin{alltt}
vector goal(unsigned int Aseed, int n) \verb"{"
  int i;
  matrix A;
  vector x, b;
  i = 1;
  A = makeMatrix(Aseed);
  while (i < n) \verb"{"
    x = makeVector(i * 523 % RANDMAX);
    b = mulMatVec(A, x);
    printstatus("/* solving A * x(i) = b for i = %d */\verb"\"n", i);
    solve(A, b);
    i++;
  \verb"}"
  x = makeVector(i * 523 % RANDMAX);
  b = mulMatVec(A, x);
  return solve(A, b);
\verb"}"
\end{alltt}
Using "Aseed" to generate a pseudo-random matrix "A", 
 it generates "n" different "b" vectors and
solves "Ax" = "b". Try specializing this goal function with residual
"n" and spectime "Aseed" = 17 by typing \UserTypes{gmake timing1}. What is
the problem? Look at the annotated program by typing
\UserTypes{cmixshow mtrix1.ann}; before reading on, consider
what the reason for this problem is?  \midrule

The problem here is \emph{infinite specialization:} the counter "i" in
the while loop is spectime, but the loop is controlled by the
\emph{residual} limit "n". As \cmix{} doesn't know the value of "n"
yet, it tries to specialize for "i"=1,2,3,\ldots, never terminating.

Solve the problem by inserting a  "#pragma" (a correct
solution can be seen in "answr1.c"). Find the speedup and code
blowup for the solver with matrix "A" as a spectime constant by typing
\UserTypes{gmake timing1}.


\paragraph{Interesting, time-consuming exercise:}
Make a copy of the file "mtrix1.c", call it "mtrix2.c", and make
some of your 
own matrix and vector operations, e.g.\ dot product, matrix
multiplication and addition, multiplication with a constant, etc. Try
specializing an expression like $cA + b \cdot d$ where $c$ is a
spectime simple constant, $A$ a residual matrix, $b$ a spectime vector
constant, and $d$ a residual vector, by typing 
\UserTypes{gmake timing2}. What are the speedups like?

It can be desirable to do algebraic reductions like $0A = \mathbf{0}$,
$1A = A$, $\mathbf{0} \cdot b = \mathbf{0}$, $\mathbf{1} \cdot b = b$.
This can be done by inserting tests like "if (c == 1) return A"; if
"c" is a spectime constant, matrix "A" is not rebuilt by a lot of
additions and multiplications, but simply returned unchanged, and the
test disappears from the residual program! This technique is called
\emph{partial evaluation with selective simplification}. What are the
speedups for $cA + b \cdot d$ like when $c$ or $b$ are $0$ or $1$?



\tutorsection{Exercise: FFT}
\label{sec:FFT}

The FFT (Fast Fourier Transform) algorithm implements a discrete
Fourier transformation, and has been subject for numerous
hand-optimizations. Given an array of data, FFT first ``scrambles''
the data, which enables a second phase to use a divide-and-conquer
algorithm to compute the resulting array. The first phase only
moves data around, whereas the second phase does actual computations,
including multiplications, additions and calls to math library
functions.


\paragraph{Exercise:}

In the "fft" directory you will find a file "fft1.c" containing a
generic implementation of FFT. Input is copied from a set of external
arrays, "orig_real" and "orig_imag", which are initialized by a
"generate_data" function that takes a seed "q" to generate some test
data. The size of the arrays is defined in file "fft.h". Try
specializing "fft1.c" by typing \UserTypes{gmake}; how big 
is the speedup and code blowup?.
Compare the source file with the residual file "fft1-res.c": what
seems to be the main source of speedup for the FFT?
\midrule

Given that the "fft" function operates on an array of values, it must
perform a fair amount of array indexing, but as the size of the array
is fixed, \cmix{} can actually do this indexing at specialization
time!


\paragraph{Beginner's exercise:}

Try specializing the FFT in file "answr2.c" by typing
\UserTypes{gmake answer2}. Compare residual programs
"fft1-res.c" and "answr2-res.c": how does specialization time indexing
manifest itself? Does it have an effect on the speedup?
Also, take a look at the "real" and "imag" array definitions in the
annotated source program by typing
\UserTypes{cmixshow answr2.ann}.


\paragraph{Advanced exercise:}

Make a copy of file "fft1.c", call it "fft2.c", and change it to
achieve spectime indexing of the "real" and "imag" arrays (a solution
can be found in "answr2.c"). Try it out by typing
\UserTypes{gmake timing2}; compare residual code, speedups and code
blowups with the previous specialization.
\midrule


Specializing away array indexing into arrays containing residual data is
achieved by \emph{array splitting}, in which the residual code
contains individual variables for the elements of the array. For
instance, a \emph{spectime} array of \emph{residual} values, 
"int d[3]", will result in residual variables 
"int d0, d1, d2". The choice as to whether an array of residual data is
split or not  
depends on the \emph{pointers} used to point to the array elements: the
array will be split exactly when they are \emph{spectime} pointers to
residual data. Note that during the internal transformation in \cmix{}
from C to Core C plain integer array indexing like "a[i + 42]" is
converted into pointer manipulation.

In the present example, we split the array by removing the
"#pragma" that forces the second and third parameters of
"fft(int is, REAL *fr, REAL *fi)" to become residual pointers.



\tutorsection{Exercise: Ray tracer}
\label{sec:RayTracer}

A \emph{ray tracer} is a program for producing images of
scenes that consist of various objects, viewed from a specific
direction, illuminated with some light sources etc. Each object, view
direction, light source etc.\ are described by coordinates in a
euclidian space, and the ray tracer then traces all the light rays
backwards from the viewer's eyepoint to the objects in the scene,
changing direction if it hits a reflecting object.


In the "ray" directory you will find a simple ray tracer capable of
tracing images containing squares, discs and spheres with uniform
or checked surfaces. It consists of the following files:
\begin{center}\small
\begin{tabular}{ll}
  "ray.c"     & The main tracer functions to be specialized \\
  "scenes.c"  & A number of scenes to trace \\
  "main.c"    & The user interface \\
  "create.c"  & Utility functions for creating objects in the scene \\
  "vector.c"  & Utility vector functions \\
  "mypower.c" & The power function \\
  "plotOpenGL.c"& Utility functions for producing screen graphics
                  using OpenGL\\
  "plotsrgp.c"& Utility functions for producing screen graphics using SRGP\\
  "plotptc.c" & Utility functions for producing screen graphics using PTC\\
  "tiff.c"    & Utility functions for saving images to TIFF files\\
  "lowerarity.c" 
              & A mediator between "main.c" and the residual goal function \\
  "ray1.cmx"  & Specializer directives for \cmix \\
\end{tabular}
\end{center}
The goal function 
"draw_scene(width, height, scenenum, color)" is located in "ray.c". It
draws one of the scenes found in "scenes.c".

The entire ray tracer can be built by typing \UserTypes{gmake ray}.


\paragraph{Beginner's exercise:}

Try specializing the ray tracer with respect to the first scene by
typing \UserTypes{gmake answer1}; this will use the specializer
directives in "answr1.cmx" to specialize "ray.c". Now compare
"answr1.cmx" and "ray1.cmx" and explain why the differences are
necessary to avoid infinite specialization.


\paragraph{Advanced exercise:}

Specializing "draw_scene" right away by typing 
\UserTypes{gmake timing1} turns out to produce infinite
specialization. Take a look at the "draw_scene" function: find
the cause of this problem and remedy it by inserting an appropriate
directive in "ray1.cmx" (an answer can be found in "answr1.cmx").
\midrule

Note that on most systems, sending the image data to the computer display
constitutes a bottleneck, so it is hard to get a realistic picture of the
speedup by showing the tracing process simultaneously in two
windows. It is better to time first the source program and then the
residual program, or to time both simultaneously without sending any
data to the display.

Specializing the ray tracer can quickly produce very large residual
code for scenes with many objects. To avoid excessive code blowup it
can be necessary to force some variables to be residual.


\paragraph{Hard exercise: avoiding code blowup}

Make a copy of "ray1.cmx", call it "ray2.cmx"
Try specializing the ray tracer with respect to scene 5 by typing
\UserTypes{gmake timing2}. While you are waiting for the generating
extension to finish, open another window and look at the memory usage
(e.g.\ by running the "top" program). When you are convinced that the
specialization will not terminate before the memory is exhausted,
abort the specialization.

Now look at the residual program, find the source of code blowup and
insert directives in "ray2.cmx" to force the appropriate variable(s) to
be residual. Of course you should not make too much residual, or you
will sacrifice the speedup! (An answer can be found in "answr2.cmx".)

}
%%% Local Variables:
%%% mode: latex
%%% TeX-master: shared
%%% End:
