spectral: remove salishan
authorMichal Terepeta <michal.terepeta@gmail.com>
Mon, 13 Mar 2017 22:34:44 +0000 (18:34 -0400)
committerBen Gamari <ben@smart-cactus.org>
Mon, 13 Mar 2017 23:44:06 +0000 (19:44 -0400)
There's no Haskell code in `spectral/salishan`, so let's just remove it.

Signed-off-by: Michal Terepeta <michal.terepeta@gmail.com>
Test Plan: build & run

Reviewers: bgamari

Subscribers: snowleopard

Differential Revision: https://phabricator.haskell.org/D3321

16 files changed:
spectral/Makefile
spectral/salishan/ada.tex [deleted file]
spectral/salishan/doctors/sisal/doctors.if1 [deleted file]
spectral/salishan/doctors/sisal/doctors.sis [deleted file]
spectral/salishan/hamming/sisal/hamming.if1 [deleted file]
spectral/salishan/hamming/sisal/hamming.sis [deleted file]
spectral/salishan/haskell.tex [deleted file]
spectral/salishan/id.tex [deleted file]
spectral/salishan/occam.tex [deleted file]
spectral/salishan/paraffins/sisal/paraffins.if1 [deleted file]
spectral/salishan/paraffins/sisal/paraffins.sis [deleted file]
spectral/salishan/scheme.tex [deleted file]
spectral/salishan/skyline/sisal/skyline.if1 [deleted file]
spectral/salishan/skyline/sisal/skyline.in [deleted file]
spectral/salishan/skyline/sisal/skyline.sis [deleted file]
spectral/salishan/unity.tex [deleted file]

index c056f4c..e60718d 100644 (file)
@@ -8,8 +8,7 @@ SUBDIRS = ansi atom awards banner boyer boyer2 calendar cichelli circsim \
          puzzle rewrite scc simple sorting sphere treejoin
 
 # compreals    no suitable test data
-# salishan     no Haskell code!
-OTHER_SUBDIRS = compreals lambda last-piece salishan secretary triangle
+OTHER_SUBDIRS = compreals lambda last-piece secretary triangle
 
 include $(TOP)/mk/target.mk
 
diff --git a/spectral/salishan/ada.tex b/spectral/salishan/ada.tex
deleted file mode 100644 (file)
index 4f55fd9..0000000
+++ /dev/null
@@ -1,3862 +0,0 @@
-%%   format=book
-
-\Doc[]
-\DivBod[]
-\DivLii[]\HdMjLii[\def\HdMjLiiJust{C}\def\HdMjLiiInit{}\def\HdMjLiiUnderln{F}\def\HdMjLiiNumPostpunc{}\def\HdMjLiiNumFirstdisp{99}\def\HdMjLiiFntGenlTsz{N}]Ada
-Solutions to\newlinetag[]
-the Salishan Problems\HdMjEndii[]
-\HdMiscLvi[\def\HdMiscLviFntTsz{K}]Kenneth W. Dritz%
-\HdMiscEndvi[]
-\HdMiscLvi[\HdMiscLviStyAPosPostvskp=0pt \HdMiscLviStyAPosPrevskp=0pt ]Mathematics
-and Computer Science Division\HdMiscEndvi[]
-\HdMiscLvi[\HdMiscLviStyAPosPostvskp=0pt \HdMiscLviStyAPosPrevskp=0pt ]Argonne
-National Laboratory\HdMiscEndvi[]
-\HdMiscLvi[\HdMiscLviStyAPosPostvskp=20pt plus7pt minus4pt \HdMiscLviStyAPosPrevskp=0pt ]Argonne,
-Illinois 60439-4801\HdMiscEndvi[]
-\Para[]This chapter presents, in Sections \Xref[\def\XrefName{Hamming}]
-through \Xref[\def\XrefName{skyline}], revised Ada solutions to the
-four challenge problems featured in the Language Sessions of the Conference
-on High-Speed Computing held in Gleneden Beach, Oregon in March 1988.
-The chapter begins with an overview of Ada, emphasizing features that
-are noteworthy in the problem solutions.\Endpara[]
-\DivLiii[]\HdMjLiii[]Language Features Relevant to the Salishan Problems%
-\HdMjEndiii[]
-\Para[]Ada is a high-level procedural language, with strong typing
-and other features common in languages of its genre, as well as with
-several innovations. The language has had an influence in such related
-areas as program development environments and software life-cycle
-design methodology, so that in a broad sense one can talk about \ldquo[]the
-Ada movement.\rdquo[] In this section, we cannot hope to provide a
-complete introduction to the language or to the modern software engineering
-principles that it supports especially well. For general background,
-we refer the reader to any of the many excellent textbooks on Ada;
-for the details, the language reference manual is indispensable, and
-the textbooks are also valuable. Here, we\rsquo[]ll concentrate on
-those features particularly relevant to the Salishan Problems\EmDash[]namely,
-the tasking features that support concurrency and some of those supporting
-data structuring and abstraction. The language features described
-here, and used in the problem solutions, are those of Ada as standardized
-in 1983 \Cit[\def\CitId{ANSI:AdaRM}]\Endcit[]. The revision currently
-in progress, known informally as Ada 9X \Cit[\def\CitId{Ada9X:DraftReq}]%
-\Endcit[], can be expected to allow some aspects of our solutions
-to be more efficient and to be expressed more elegantly.%
-\Endpara[]
-\Para[]As is well known, the language was created in response to the
-\ldquo[]software crisis\rdquo[] in the U. S. Department of Defense,
-a crisis characterized by rapid escalation of the cost of developing,
-maintaining, and adapting software while hardware costs were decreasing
-\Cit[\def\CitId{Booch:SoftEng,Cohen:2ndLang}]\Endcit[]. Part of the
-problem lay in the programming languages being used by the defense
-services, and especially the number of those languages and the lack
-of interoperability among them. Another major part of the problem
-was the inadequate support for modern principles of software engineering,
-both in the languages themselves and in the programming environments
-surrounding them. By mandating a single high-level language designed
-to support such principles as data abstraction, information hiding,
-both top-down and bottom-up design, secure programming, and reusability,
-the DoD expected to reduce the cost of software and increase its reliability,
-significantly.\Endpara[]
-\DivLiv[]\HdMinLiv[]Tasking Features\HdMinEndiv[]
-\Para[]Much DoD software is for embedded systems, which have unique
-requirements for low-level I/O, asynchronous interrupts, parallelism,
-and real-time control. Tasking features were mandated for the new
-language by the Steelman requirements \Cit[\def\CitId{DoD:Steelman}]%
-\Endcit[] in 1978. A high-level model of parallelism was adopted;
-based essentially on CSP \Cit[\def\CitId{Hoare:CSP}]\Endcit[], it
-employs the concept of a \txtxemph[]rendezvous\txtxendemph[] between
-tasks both for synchronization and for communication. Ada successfully
-marries the high-level model of concurrency with low-level features;
-for example, asynchronous interrupts, whose behavior is defined in
-terms of \ldquo[]virtual\rdquo[] tasks in the high-level model, bring
-certain low-level features\EmDash[]such as representation clauses\EmDash[]into
-play. Our interest here is not in these low-level features, but rather
-in the high-level model of tasking.\Endpara[]
-\Para[]Ada programs are strictly serial except where tasking is explicitly
-used to express concurrency. (Ada 9X, however, is likely to allow
-some degree of implicit parallelism so that, for example, vector architectures
-can be exploited.) If a multiprocessor or distributed implementation
-of Ada is available, concurrency\EmDash[]appropriately used\EmDash[]can
-provide some speedup. A more important role for concurrency, however,
-is as a cognitive tool, like recursion; in that role, it can simplify
-the expression of certain algorithms\EmDash[]particularly nondeterministic
-ones, for which it is well suited. (Failure to exploit nondeterminism
-by specifying an ordering where none is needed is an error of %
-\txtxemph[]overspecification\txtxendemph[]; it can lead to inefficiency
-or, in some cases, to incompleteness.) The goal of achieving speedup,
-when the hardware permits it, should be secondary; indeed, concurrent
-Ada programs can be written without regard to the hardware on which
-they will eventually be run, because they will in fact run (without
-speedup) on uniprocessors, where the implementation of Ada achieves
-the illusion of concurrency by interleaving or time-slicing among
-the Ada tasks eligible for execution.\Endpara[]
-\Para[]The rendezvous model of tasking in Ada is at a higher level
-than that of monitors \Cit[\def\CitId{Hoare:Monitors}]\Endcit[], which
-are favored by some researchers for the ease with which they can be
-efficiently implemented using lightweight hardware locks. Of course,
-implementation of the rendezvous mechanism typically makes use of
-locks and locking internally, out of sight of the application programmer.
-And realization of the monitor paradigm within an Ada program, when
-desired for its logical properties, is easily achieved with the rendezvous
-mechanism. Unfortunately, because of the richness of the full semantics
-of Ada tasking, implementation of the rendezvous mechanism has not
-heretofore been efficient enough to allow monitors coded in Ada to
-compete favorably with those handcrafted directly out of locks and
-locking operations in other languages, or with those provided as primitive
-operations in other languages (without all the semantic richness of
-Ada). Increasingly, however, compiler vendors are making their compilers
-smart enough to recognize when the rendezvous (without the more costly
-features of the language) is used in a monitor metaphor, and by implementing
-the so-called \ldquo[]Habermann-Nassi optimization\rdquo[] %
-\Cit[\def\CitId{HabNas:TaskOpt}]\Endcit[] they are specializing the
-code generation in that case to match the best implementations of
-monitors in other languages. Nevertheless, new features are anticipated
-in Ada 9X to provide for efficient mutually exclusive accesses to
-shared data by concurrent tasks.\Endpara[]
-\Para[]A \txtxemph[]task\txtxendemph[] is a kind of Ada program unit
-like a procedure, except that it has a separate thread of control
-and cannot have formal parameters. Like other program units, tasks
-come in two separate parts\EmDash[]a specification and a body. A task\rsquo[]s
-\txtxemph[]specification\txtxendemph[] serves to define the visible
-interface between the task and other program units that might interact
-with it, while its \txtxemph[]body\txtxendemph[] expresses its logical
-behavior. Tasks can be defined either as individual objects (%
-\txtxemph[]single tasks\txtxendemph[]) or as types; in the latter
-case, any number of identical objects of the type can be created,
-perhaps as components of composite objects (such as arrays).%
-\NtFoot[]\NtNtpar[]The inability to parameterize tasks is especially
-felt when similar tasks are aggregated into arrays and set to work
-on different parts of a problem\EmDash[]a recurring strategy in several
-of the following problem solutions. At present, the rendezvous mechanism
-must be used to communicate with tasks to give them some idea of their
-own \ldquo[]identity.\rdquo[] Mechanisms for parameterizing tasks
-have been proposed for Ada 9X; these have the prospect of eliminating
-some of the tasking communication in our solutions, thereby simplifying
-them.\NtEndntpar[]\NtEndfoot[] Tasks, like other objects, can be created
-either by \txtxemph[]elaborating\txtxendemph[] (giving effect to)
-object declarations upon entering the scope of those declarations,
-or by evaluating \txtxemph[]allocators\txtxendemph[] (the mechanism
-for dynamic allocation in Ada); they start executing upon creation.%
-\NtFoot[]\NtNtpar[]This is a simplification, but appropriate for this
-introduction.\NtEndntpar[]\NtEndfoot[] In the doctor\rsquo[]s office
-problem, for example, the receptionist is modeled as a single task;
-the patients are modeled as an array of tasks of some appropriate
-task type; and the doctors are modeled as individually created objects
-of another task type, using allocators. (The reason that two different
-techniques were used to manage these collections is discussed in the
-problem solution.)\Endpara[]
-\Para[]Tasks that work on disjoint sets of data and that never cooperate
-are uninteresting. More typically, tasks either share global data
-and synchronize (serialize) their references to them, or they own
-data outright and rely on the queuing and mutual exclusion of other
-tasks\rsquo[] interactions with themselves, plus the single thread
-of control within themselves, to serialize references to the data.
-In the latter case, values usually are transmitted between interacting
-tasks. The synchronization and the communication aspects of the interaction
-are combined in the rendezvous mechanism.\Endpara[]
-\Para[]Once created, tasks execute in parallel with the rest of the
-program until they terminate or reach some kind of synchronization
-point\EmDash[]for example, that determined by a rendezvous with another
-task.\Endpara[]
-\Para[]In the simplest kind of rendezvous, the \ldquo[]calling task\rdquo[]
-makes an \txtxemph[]entry call\txtxendemph[] to an \txtxemph[]entry%
-\txtxendemph[] of the \ldquo[]called task.\rdquo[] (Entries of a task
-are declared in its specification.) An entry call has the syntax of
-a procedure call, except that the name involved is an %
-\txtxemph[]expanded name\txtxendemph[] (for example, %
-\tyxffmxmono[]t.e\tyxffmxendmono[]) combining the name of the called
-task (\tyxffmxmono[]t\tyxffmxendmono[]) and that of an entry (%
-\tyxffmxmono[]e\tyxffmxendmono[]) within it. Like a procedure call,
-an entry call can optionally include actual parameters, so it can
-pass values to, and receive them from, the called task.%
-\Endpara[]
-\Para[]The called task\rsquo[]s role in a simple rendezvous is expressed
-by an \txtxemph[]accept statement\txtxendemph[], an executable statement
-whose syntax is depicted in Figure \Xref[\def\XrefName{syntax-of-accept}].%
-\NtFoot[]\NtNtpar[]Throughout our code examples, Ada keywords, which
-are reserved words, will be emboldened. This will distinguish them
-well enough from identifiers to allow both to be written in lower
-case. Ada keywords appearing in ordinary text will also be emboldened
-whenever some kind of punctuation seems appropriate.%
-\NtEndntpar[]\NtEndfoot[]
-\FgBlock[\def\FgBlockPlace{H}]
-\Parbox[]
-\FgCap[\def\FgCapId{syntax-of-accept}]Syntax of the accept statement%
-\FgEndcap[]
-\Comp[]\tyxtstxbf[]accept\tyxtstxendbf[] \Symlt[]\tyxtstxit[]entry-name%
-\tyxtstxendit[]\Symgt[] \Symlbk[](\Symlt[]\tyxtstxit[]formal-parameter-list%
-\tyxtstxendit[]\Symgt[])\Symrbk[] \Symlbk[]\tyxtstxbf[]do%
-\tyxtstxendbf[]
-   \Symlt[]\tyxtstxit[]statement-list\tyxtstxendit[]\Symgt[]
-\tyxtstxbf[]end\tyxtstxendbf[] \Symlbk[]\Symlt[]\tyxtstxit[]entry-name%
-\tyxtstxendit[]\Symgt[]\Symrbk[]\Symrbk[];\Endcomp[]
-\EndParbox[]
-\FgEndblock[]
- If the accept statement has formal parameters, their scope extends
-only to the end of the statement (i.e., to the semicolon in Figure
-\Xref[\def\XrefName{syntax-of-accept}]). The semantics of a rendezvous
-are as follows. The first of the two tasks to execute its part of
-the rendezvous (that is, either the entry call in the calling task
-or the accept statement in the called task) becomes suspended until
-the other task executes its corresponding part. At that point, if
-the statement list is present, the calling task becomes suspended
-(if it is not already so), and the called task executes the statement
-list; the statement list may, of course, read the formal parameters
-of mode \tyxffmxmono[]\tyxtstxbf[]in\tyxtstxendbf[]%
-\tyxffmxendmono[] or \tyxffmxmono[]\tyxtstxbf[]in\tyxtstxendbf[]%
-\tyxffmxendmono[] \tyxffmxmono[]\tyxtstxbf[]out\tyxtstxendbf[]%
-\tyxffmxendmono[], whose values have been transmitted from the calling
-task, and store into the formal parameters of mode %
-\tyxffmxmono[]\tyxtstxbf[]out\tyxtstxendbf[]\tyxffmxendmono[] or %
-\tyxffmxmono[]\tyxtstxbf[]in\tyxtstxendbf[]\tyxffmxendmono[] %
-\tyxffmxmono[]\tyxtstxbf[]out\tyxtstxendbf[]\tyxffmxendmono[]. Finally,
-when the end of the statement list is reached (or in its absence),
-both tasks continue in parallel\EmDash[]the calling task with the
-statement after its entry call and the called task with the statement
-after its accept statement. On the calling side, the actual parameters
-that had been associated with formal parameters of mode %
-\tyxffmxmono[]\tyxtstxbf[]out\tyxtstxendbf[]\tyxffmxendmono[] or %
-\tyxffmxmono[]\tyxtstxbf[]in\tyxtstxendbf[]\tyxffmxendmono[] %
-\tyxffmxmono[]\tyxtstxbf[]out\tyxtstxendbf[]\tyxffmxendmono[] have,
-henceforth, the new values they received during the rendezvous.%
-\Endpara[]
-\Para[]If multiple tasks call a given entry of some other task, the
-calls remain queued in FIFO order, and each execution of an accept
-statement for the entry removes the oldest call from the queue.%
-\Endpara[]
-\Para[]Conditional entry calls and accept statements (those that take
-an alternate path instead of waiting, if their counterparts have not
-already been executed) and timed entry calls and accept statements
-(those that time out and take an alternate path if their counterparts
-are not executed within a specified time) can be constructed, but
-we do not need them for the problem solutions. And entries of a task
-can be aggregated into \txtxemph[]entry families\txtxendemph[], which
-behave like arrays of entries and provide for the identity of an entry
-named in an entry call or accept statement to be computed (e.g., by
-the value of its subscript expression); the problem solutions do not
-require entry families, either.\Endpara[]
-\Para[]Finally, tasks can be made to accept entry calls at any of
-several alternative entries. To achieve that effect, the called task
-executes what is called a \txtxemph[]selective wait%
-\txtxendemph[], the syntax of which is illustrated (by means of a
-skeletal example) in Figure \Xref[\def\XrefName{syntax-of-selective-wait}].
-\FgBlock[\def\FgBlockPlace{H}]
-\Parbox[]
-\FgCap[\def\FgCapId{syntax-of-selective-wait}]Syntactic example of
-a selective wait\FgEndcap[]
-\Comp[]\tyxtstxbf[]select\tyxtstxendbf[]
-   \Symlt[]\tyxtstxit[]accept-statement\tyxtstxendit[]\Symgt[]
-   \Symlbk[]\Symlt[]\tyxtstxit[]statement-list\tyxtstxendit[]\Symgt[]\Symrbk[]
-\tyxtstxbf[]or\tyxtstxendbf[]
-   \Symlt[]\tyxtstxit[]accept-statement\tyxtstxendit[]\Symgt[]
-   \Symlbk[]\Symlt[]\tyxtstxit[]statement-list\tyxtstxendit[]\Symgt[]\Symrbk[]
-\tyxtstxbf[]or\tyxtstxendbf[]
-   ...
-\tyxtstxbf[]end\tyxtstxendbf[] \tyxtstxbf[]select\tyxtstxendbf[];%
-\Endcomp[]
-\EndParbox[]
-\FgEndblock[]
- If one or more of the entries named in the accept statements have
-already been called when the task reaches its selective wait, then
-one of those calls is chosen (in a manner not defined by the language),
-and a rendezvous is performed with the task making the call; at the
-conclusion of the rendezvous, the statement list (if any) following
-the accept statement that participated in the rendezvous is executed
-in parallel with calling task. On the other hand, if no task has yet
-called any of the entries named in the accept statements, the task
-executing the selective wait becomes suspended until some task calls
-one of those entries, at which time it performs a rendezvous with
-that task. Other options can be used to add the conditional or timed
-behavior to a selective wait.\Endpara[]
-\Para[]The branches of a selective wait are called \txtxemph[]selective
-wait alternatives\txtxendemph[], of which there are several kinds.
-Those shown in Figure \Xref[\def\XrefName{syntax-of-selective-wait}]
-are \txtxemph[]accept alternatives\txtxendemph[]. Any of the selective
-wait alternatives can be prefixed by a \txtxemph[]guard%
-\txtxendemph[] containing a Boolean expression. When the task reaches
-a selective wait, all of the guards are evaluated first. A selective
-wait alternative whose guard evaluates to \tyxffmxmono[]true%
-\tyxffmxendmono[], or one without a guard, is said to be \ldquo[]open.\rdquo[]
-Only the open alternatives are considered further in the execution
-of the selective wait. The Boolean expressions in guards typically
-involve task-local \ldquo[]state\rdquo[] variables. The use of guards
-is an essential ingredient in the realization of monitors that can
-suspend a task requesting a monitor operation, when that operation
-cannot be performed until some other task first performs a complementary
-monitor operation. (An example of such a monitor might be one that
-buffers items among a collection of tasks. The operation of delivering
-an item from the buffer to a requesting task cannot be performed when
-the buffer is empty; it must wait until some other task first performs
-the complementary operation of placing an item into the buffer. A
-guard would be used to inhibit the acceptance of an entry call requesting
-delivery of an item when the buffer is empty.)\Endpara[]
-\Para[]This capability of waiting for interactions with any of several
-other tasks is crucial to the functioning of the solution to the doctor\rsquo[]s
-office problem. There, the receptionist must wait for requests by
-free doctors for sick patients, or notifications by patients that
-they are sick and in need of a doctor. These interactions can occur
-in an arbitrary and unpredictable order, and the receptionist must
-respond to each as it occurs. Guards play a crucial role in that solution,
-too; they are used to defer the receptionist\rsquo[]s interactions
-with free doctors until it knows that sick patients exist. Much of
-the desired behavior of the problem solution, including the queuing
-of doctors and patients until they can be paired up, is obtained for
-free from the semantics of the Ada tasking features.\Endpara[]
-\Para[]Termination of tasks in Ada is a deep subject unto itself,
-and we will give here only the briefest sketch of the possibilities.
-One way that tasks can terminate is by reaching the end of their execution
-(but they will wait at that point until all of their subtasks, if
-any, have terminated). A further way, expressed by another kind of
-selective wait alternative (a \txtxemph[]terminate alternative%
-\txtxendemph[]), is more appropriate for tasks, such as monitors,
-that repetitively perform services for other tasks as long as those
-services are needed. Informally, this latter mechanism allows a service
-task to terminate, instead of waiting for a future entry call, when
-the receipt of an entry call from any task that could interact with
-it is no longer possible\EmDash[]that is, when all such tasks have
-either already terminated or are similarly stating their willingness
-to terminate instead of taking another entry call. Typically, when
-one task terminates by this mechanism, others (with which it could
-interact) do so at the same time, hence the name \ldquo[]distributed
-termination\rdquo[] for this mechanism. Distributed termination
-happens not to be used in the problem solution.\Endpara[]
-\Para[]Although the morphological similarity of tasks and procedures
-has already been mentioned, it is clearly not correct to think of
-a whole task as the smallest unit of parallel execution. Tasks typically
-alternate between periods of suspension and execution, and the latter
-can be made as large or as small as is appropriate to the application
-at hand. It is also a mistake to think that Ada tasks are bound in
-a fixed way to processors or nodes of a multiprocessor system, with
-those processors or nodes frequently becoming blocked. Ada implementations
-typically maintain a queue of Ada tasks that are eligible for execution
-(not suspended), and each processor takes a task from that queue when
-its previous task terminates or becomes suspended. In some cases,
-the redirection of a processor\rsquo[]s attention from one task to
-another can even be performed without a context switch (as, for example,
-with Habermann-Nassi optimization).\Endpara[]
-\Para[]A frequent criticism of Ada is its wordiness in comparison
-to other languages. In our context this shows up, for example, in
-the repetition of parameter profiles for task entries in both the
-specification and the body of a task. (The same kind of repetition
-occurs in subprogram specifications and bodies.) This particular kind
-of repetition can be attributed to the requirements of a powerful
-language feature called \txtxemph[]subprogram overloading%
-\txtxendemph[], which can play an important role in the design of
-abstractions. In general, the wordiness of Ada is sometimes a consequence
-of powerful language features and sometimes a consequence of the redundancy
-that both tames the power and increases the safety of programs (by
-enabling extensive compile-time checking). Because of what it represents,
-most Ada programmers quickly learn to accept the wordiness as an asset
-rather than a hindrance.\Endpara[]
-\Para[]Ada appears to be a good language in which to express a solution
-to the doctor\rsquo[]s office problem because the actors in the problem,
-and the interactions among them, map directly onto available features
-of Ada. The pairwise interactions among the various actors are reminiscent
-of the rendezvous itself; the desired kind of queuing is obtained
-for free; and the merging of signals, as it were, is provided by the
-selective wait. The first two of the four solutions to Hamming\rsquo[]s
-problem also appear attractive in Ada, given the abstraction of a
-stream, which\EmDash[]while not built into the language\EmDash[]is
-readily programmed in Ada. Those solutions are comparable to others
-in this book, in languages in which streams are either built in (as
-in SISAL \Cit[\def\CitId{Skedz:SISAL}]\Endcit[]) or available as a
-previously programmed reusable\NtFoot[]\NtNtpar[]What we mean by %
-\txtxemph[]reusable\txtxendemph[] is \txtxemph[]as general as possible,
-so that it can be used in a wide variety of applications requiring
-the same general behavior, irrespective of differences in irrelevant
-details\txtxendemph[]. In Ada, reusability is achieved primarily through
-the definition and instantiation of generic units, especially generic
-packages. Streams of values of an arbitrary type are an obvious candidate
-for a reusable abstraction; though the type of the values held in
-a stream might vary with different applications, or even with different
-streams in a single application, the operations on streams are independent
-of that type. We purposely do not show how to program a generic \ldquo[]streams\rdquo[]
-package in Ada because it is highly likely that, in a mature working
-environment, the programmer desiring to solve Hamming\rsquo[]s problem
-would find that someone previously had a need for the stream abstraction
-and that a generic package exporting the desired type and operations
-(perhaps with different names than we have used) already exists in
-a local library. Such a library can be considered to extend the language.%
-\NtEndntpar[]\NtEndfoot[] abstraction. The remaining two solutions
-to Hamming\rsquo[]s problem appear less attractive, but only because
-they are considerably more involved than the usual solutions.%
-\Endpara[]
-\DivEndiv[]
-\DivLiv[]\HdMinLiv[]Data Structuring and Abstraction Features%
-\HdMinEndiv[]
-\Para[]Among the features useful for defining complex data structures
-and abstractions, and for making them reusable, are packages, generic
-units, private types, access types, record types with discriminant
-parts or variant parts, and subprogram or operator overloading. The
-Ada problem solutions only scratch the surface of the vast well of
-potential benefits these features offer. Opportunities for their use
-suggested themselves quite naturally during the development of the
-solutions.\Endpara[]
-\Para[]\txtxemph[]Packages\txtxendemph[] are one of the four kinds
-of program units in Ada, the other three being subprograms (functions
-or procedures), tasks, and generic units. Packages contain collections
-of declarations meant to be used together. For example, a math library
-is typically constituted as a package containing mathematical subprograms.
-Abstractions are usually organized as packages that declare types\EmDash[]usually
-private types\EmDash[]as well as explicitly defined operations applicable
-to objects of those types. Like other program units, packages have
-separate specifications and bodies. The declarations in a package
-specification, or rather in the part of a package specification called
-its \txtxemph[]visible part\txtxendemph[], are the ones exported to
-the user, or client, of the package. A package specification can include,
-among other things, declarations of types, declarations of objects,
-and the specifications of other (nested) program units of any of the
-four kinds. A package body contains the bodies of the program units
-whose specifications occurred in its specification; it may also include
-other declarations of types, objects, and program units, which are
-visible only there (i.e., they are not visible to the client of the
-package). Some packages do not need bodies; in particular, a package
-specification that declares only types and objects does not require
-a body.\Endpara[]
-\Para[]A package specification occurring alone as a compilation unit
-defines a \txtxemph[]library package\txtxendemph[]; the specifications
-of subprograms and of generic units occurring alone as compilation
-units also define library units. (Tasks cannot occur alone, but must
-always be nested inside another program unit. This rule is connected
-to the semantics of distributed termination of tasks. Tasks may, of
-course, be nested inside library packages.) A library unit is entered
-into a program library upon its successful compilation and is thereafter
-available to potential clients. A client\EmDash[]that is, a compilation
-unit that needs the facilities provided by the library unit\EmDash[]refers
-to the library unit in its \txtxemph[]context clause%
-\txtxendemph[], which contains one or more \txtxemph[]with clauses%
-\txtxendemph[] optionally followed by \txtxemph[]use clauses%
-\txtxendemph[]. (We say that the compilation unit \ldquo[]withs\rdquo[]
-the library unit. In this chapter, we also say that the compilation
-unit is compiled \ldquo[]in the context of\rdquo[] the library unit.)
-A client of a library unit can be compiled before the body of the
-library unit is compiled; furthermore, the client need not be recompiled
-when, after the body of the library unit is initially compiled, it
-is subsequently changed. The specification of a library package, for
-example, contains all the interface information needed to compile
-references to the types, objects, and subprograms that the package
-exports. Thus, changes in the detailed implementation of an abstraction
-do not require the client of an abstraction to be recompiled, provided
-that the interface remains unchanged.\Endpara[]
-\Para[]The solution to Hamming\rsquo[]s problem is organized as a
-library package; the package exports a type, an internal package,
-and a procedure that solves the problem. To solve Hamming\rsquo[]s
-problem, the user writes a program unit that \ldquo[]withs\rdquo[]
-the Hamming\rsquo[]s problem package and then calls the procedure
-that it exports. To interface to that procedure, the user would also
-declare some objects of the type exported by the Hamming\rsquo[]s
-problem package and by its internal package.\Endpara[]
-\Para[]The solution to the paraffins problem is organized somewhat
-differently, in three parts: a pair of library packages (one for radicals,
-the other for molecules) that export types and operations, and a library
-function that solves the problem. To solve the paraffins problem,
-the user writes a program unit that \ldquo[]withs\rdquo[] and calls
-the function. To interface to that function, the user would also \ldquo[]with\rdquo[]
-the molecules package and declare some objects of a type exported
-by it. Depending on the other needs of the user\rsquo[]s application,
-the user might also wish to \ldquo[]with\rdquo[] the radicals package.%
-\Endpara[]
-\Para[]\txtxemph[]Generic units\txtxendemph[], which may be generic
-packages or generic subprograms, strongly support the aim of reusability
-by making it possible to parameterize packages or subprograms in a
-variety of ways. They serve as templates from which ordinary packages
-or subprograms are obtained by the process of \txtxemph[]instantiation%
-\txtxendemph[], in which \txtxemph[]generic actual parameters%
-\txtxendemph[] are associated with the generic unit\rsquo[]s %
-\txtxemph[]generic formal parameters\txtxendemph[]. Generic units
-can be parameterized with types, computed values (playing the role
-of constants inside the generic unit), variables (providing aliasing
-between variables inside and outside the generic unit), and subprograms.
-The generic actual parameters are said to be \ldquo[]imported\rdquo[]
-into a generic unit; some of those imported by a generic package may
-be re-exported by the ordinary package obtained from it by instantiation.%
-\Endpara[]
-\Para[]The solution to the doctor\rsquo[]s office problem is organized
-as a generic library procedure that imports a pair of functions. To
-solve the doctor\rsquo[]s office problem, the user writes a program
-unit that \ldquo[]withs\rdquo[] the generic procedure, instantiates
-it with the names of a pair of functions (provided by the user) giving
-the probability distributions of patients\rsquo[] healthy periods
-and doctors\rsquo[] cure times, and calls the resulting ordinary procedure.
-Parameterization by a subprogram also plays a minor role in the solution
-to the paraffins problem, where generic procedures are used (both
-as library units and internally). At present, generic units must be
-used in this way to parameterize a subprogram with another subprogram,
-but Ada 9X is expected to provide a way to do this without using generic
-units.\Endpara[]
-\Para[]The solution to the skyline matrix problem is organized as
-a generic library package importing a floating-point type and a positive
-integer value. To solve the skyline matrix problem, the user writes
-a program unit that \ldquo[]withs\rdquo[] the generic package, instantiates
-it with a floating-point type (thus customizing the problem to the
-required precision) and a positive integer value giving the order
-of the problem, declares matrices and vectors of the types exported
-by the resulting ordinary package, manipulates the matrices and vectors
-using operations exported by the package, and calls the function (also
-exported by the package) to solve the matrix equation.\Endpara[]
-\Para[]In Ada, a type is viewed as a set of values and a set of operations
-on the values. Operations of a type can be declared by the user in
-the form of a subprogram and are designated either by a name or a
-(predefined) operator symbol. In addition, operations appropriate
-to the nature of a type are implicitly declared and exported with
-the type. For one example, the declaration of a floating-point type
-implicitly declares arithmetic operations on values of the type; for
-another, the declaration of an array type implicitly declares component
-selection by subscripting as an operation of the type. The user may
-declare \txtxemph[]private types\txtxendemph[], whose significance
-is that very few operations are implicitly exported by the type declaration;
-essentially, the details of the realization of the type are hidden
-from clients. A private type is defined in the visible part of a package
-specification. A corresponding \txtxemph[]full type declaration%
-\txtxendemph[] is given in another part of the package specification,
-called the \txtxemph[]private part\txtxendemph[]. Beyond the few operations
-implicitly exported for all private types, the only other operations
-available to clients of the package are those explicitly exported
-in the form of subprograms declared in the package\rsquo[]s visible
-part. Operations relevant to the full type declaration are implicitly
-declared by it and are visible in the body of the package, but not
-to clients of the package. The use of private types is often combined
-with the use of generics to forge powerful and secure abstractions.
-Our use of private types in the solutions is limited to a brief discussion
-at the end of Section \Xref[\def\XrefName{crout-skyline}] of some
-interesting possibilities in connection with skyline matrices. However,
-in several of the problem solutions we assume the existence of generic
-library packages that provide generally useful abstractions, and these
-would certainly use private types.\NtFoot[]\NtNtpar[]All of the library
-units said in this chapter to be \ldquo[]assumed to exist\rdquo[]
-were actually written and used for testing the solutions.%
-\NtEndntpar[]\NtEndfoot[]\Endpara[]
-\Para[]Dynamic storage allocation is provided in Ada for applications
-requiring the construction of complex list or tree structures. An
-operation called an \txtxemph[]allocator\txtxendemph[] obtains storage
-for an object dynamically and returns a pointer to the newly allocated
-object. Pointer values are values of a class of types called %
-\txtxemph[]access types\txtxendemph[]. The declaration of an access
-type designates the type of the objects pointed to by values of the
-access type, upholding Ada\rsquo[]s principle of strong typing. We
-use access types in the solutions in several ways. In the paraffins
-problem, we construct molecules and radicals as trees of linked records,
-and we store those of a given size in linked lists. In the doctor\rsquo[]s
-office problem, we represent the doctors as dynamically allocated
-tasks of some task type, with each task accessed through a pointer
-serving to identify it to the receptionist and to the patient that
-it treats. In the skyline matrix problem, we dynamically allocate
-the rows and columns of skyline matrices to accommodate the components
-inside the skyline envelope without wasting space for the zero components
-outside, and in fact a skyline matrix is represented as an array of
-pointers to the row vectors of the lower triangle and another array
-of pointers to the column vectors of the upper triangle.%
-\Endpara[]
-\Para[]Two features of record types play a role in data structuring
-and abstraction in Ada: discriminant parts and variant parts. Record
-types may be declared with a \txtxemph[]discriminant part%
-\txtxendemph[], which serves to parameterize the type in certain ways.
-A discriminant part of a record type definition gives the names and
-types of special components of the record known as \txtxemph[]discriminants%
-\txtxendemph[], upon which other components may depend. Without going
-into much detail, we will simply say that the discriminants of a record
-type may be used to express the bounds of other record components
-that are arrays, and, in conjunction with \txtxemph[]variant parts%
-\txtxendemph[], they may be used to determine which of several alternate
-components exist in the record. Objects of a record type with discriminants
-are thus self-describing in terms of their layout. Depending on how
-they are declared and how they are created, such objects can either
-be constrained to have the same layout forever (i.e., the discriminants,
-once initialized, are unchangeable) or be permitted to change their
-layout as a result of assignment, within the allowable range of values
-of the discriminants as given by their types. In the problem solutions,
-we make only limited use of this facility. In the paraffins problem,
-we use discriminants and variant parts to define a record type for
-paraffin radicals that can have one of two distinct layouts and a
-record type for paraffin molecules that can also have one of two distinct
-layouts. In the skyline matrix problem, we use discriminants to hold
-the bounds of a record component that is an array. In both cases,
-the objects of the record types are dynamically allocated with constrained
-layouts.\Endpara[]
-\Para[]The final feature of interest in the problem solutions, %
-\txtxemph[]subprogram and operator overloading\txtxendemph[], refers
-to the ability to declare several different subprograms with the same
-designator (which is either a name or a predefined operator symbol)
-but different parameter/result profiles. The subprogram designated
-by a particular name or operator symbol is determined during compilation
-by overload resolution, using the parameter/result types and other
-contextual information. This feature supports abstraction by allowing
-familiar names or operator symbols to be extended to new data types.
-We use operator overloading in the solution to the skyline matrix
-problem to define an inner-product function for vectors, using the
-customary \tyxffmxmono[]*\tyxffmxendmono[] infix operator symbol (which
-is predefined as the multiplication operator for scalars); thus, we
-overload the \tyxffmxmono[]*\tyxffmxendmono[] operator. (We also mix
-\txtxemph[]named parameter association\txtxendemph[] with the more
-traditional \txtxemph[]positional parameter association%
-\txtxendemph[], particularly when it allows a subprogram invocation
-or generic instantiation to be read like an English phrase.)%
-\Endpara[]
-\Para[]In the problem solutions that follow, we discuss language features
-only to the depth required for a reader unfamiliar with the language
-to appreciate the implications, strengths, and limitations of the
-feature, and its application to the problem at hand. We make no attempt
-to describe \txtxemph[]all\txtxendemph[] the features used, however.%
-\Endpara[]
-\DivEndiv[]
-\DivEndiii[]
-\DivLiii[\def\DivLiiiId{Hamming}]\HdMjLiii[]Hamming\rsquo[]s Problem
-(Extended)\HdMjEndiii[]
-\Para[]The problem is as follows: Given a finite increasing sequence
-\InlEqn[]\LmthEqn[]p_{1},
-\ldots ,p_{k}
-\LmthEndeqn[]\EndInlEqn[] of primes and an integer \InlEqn[]\LmthEqn[]n
-\LmthEndeqn[]%
-\EndInlEqn[], output in order of increasing magnitude and without
-duplication all integers less than or equal to \InlEqn[]\LmthEqn[]n
-\LmthEndeqn[]%
-\EndInlEqn[] of the form 
-\DispEqn[]
-\DmthEqn[]
-\prod \limits _{i=1}^{k}p_{i}^{e_{i}}
-\DmthEndeqn[]\EndDispEqn[]
-for \InlEqn[]\LmthEqn[]e_{i}
-\geq 0
-\LmthEndeqn[]\EndInlEqn[]. A hint calls attention to the fact that
-if \InlEqn[]\LmthEqn[]m
-\LmthEndeqn[]\EndInlEqn[] is in the output sequence, then so is %
-\InlEqn[]\LmthEqn[]m
-\cdot p_{i}
-\LmthEndeqn[]\EndInlEqn[], provided that it is less than or equal to %
-\InlEqn[]\LmthEqn[]n
-\LmthEndeqn[]\EndInlEqn[].\Endpara[]
-\Para[]Four solutions to Hamming\rsquo[]s problem, using different
-degrees of tasking, are presented. The first is straightforward and
-uses no tasking features, while the second is a minor variation of
-the first that uses tasking in a rather artificial way to remove unnecessary
-determinism and coincidentally introduce a small amount of concurrency.
-The third implements an entirely different algorithm and uses tasking
-in a more functional way, and the fourth is an extension of the third
-in which tasks are replicated to achieve greater parallelism. While
-the fourth solution also represents an artificial improvement over
-its predecessor, the goal and the method of the improvement are unlike
-that embodied in the second solution.\Endpara[]
-\DivLiv[]\HdMinLiv[]First Solution: Usual Serial Algorithm%
-\HdMinEndiv[]
-\Para[]The usual method of solving this problem involves several parallel
-streams of future output values, one stream corresponding to each
-prime. In each iteration of the \ldquo[]main loop,\rdquo[] a value
-is appended to the tail of each stream, a new output value is produced,
-and a value is removed from the head of some of the streams. More
-precisely, each time through the loop,
-\LstList[]
-\LstItem[]the product of the previous output value and the prime associated
-with the stream is appended to each stream;\LstEnditem[]
-\LstItem[]the least of the values at the heads of all the streams
-is determined, and it becomes the next output value; and%
-\LstEnditem[]
-\LstItem[]each stream whose head matches that least value has its
-head removed.\LstEnditem[]
-\LstEndlist[]
-\Endpara[]
-\Para[]Streams are not predefined in Ada, but we assume the availability,
-as a library unit, of a generic package named \tyxffmxmono[]streams%
-\tyxffmxendmono[] that provides an abstract data type called %
-\tyxffmxmono[]stream\tyxffmxendmono[] complete with appropriate operations
-on objects of that type. Since we need streams of positive integers,
-we instantiate the generic package \tyxffmxmono[]streams%
-\tyxffmxendmono[] with the predefined subtype \tyxffmxmono[]positive%
-\tyxffmxendmono[] of the predefined type \tyxffmxmono[]integer%
-\tyxffmxendmono[] to obtain a package that we call %
-\tyxffmxmono[]positive\Symuns[]streams\tyxffmxendmono[]; its %
-\tyxffmxmono[]stream\tyxffmxendmono[] type is exactly what we seek.
-We are not concerned here with the implementation of the generic package,
-which might very well use pointers and linked lists, and for brevity
-we omit even its specification. We assume that the initial state of
-an object of type \tyxffmxmono[]stream\tyxffmxendmono[] is \ldquo[]empty,\rdquo[]
-allowing us to dispense with explicit initialization of streams; this
-is a realistic assumption since access objects, i.e., pointers, are
-automatically initialized to \tyxffmxmono[]\tyxtstxbf[]null%
-\tyxtstxendbf[]\tyxffmxendmono[] in Ada. In this application, we require
-only the following operations on streams, which we assume are provided
-by the generic package: a procedure (\tyxffmxmono[]append%
-\tyxffmxendmono[]) to append a value to the tail of a stream; a function
-(\tyxffmxmono[]head\tyxffmxendmono[]) to return the value at the head
-of a nonempty stream without removing it; and a procedure (%
-\tyxffmxmono[]behead\tyxffmxendmono[]) to remove and discard the value
-at the head of a nonempty stream. The subprograms \tyxffmxmono[]head%
-\tyxffmxendmono[] and \tyxffmxmono[]behead\tyxffmxendmono[] can be
-assumed to raise some exception if applied to an empty stream. We
-have no need for an \tyxffmxmono[]is\Symuns[]empty%
-\tyxffmxendmono[] predicate; and because we apply \tyxffmxmono[]head%
-\tyxffmxendmono[] and \tyxffmxmono[]behead\tyxffmxendmono[] only to
-nonempty streams, we can guarantee that the exception will never be
-raised.\Endpara[]
-\Para[]Our first solution to Hamming\rsquo[]s problem is in the form
-of a package, \tyxffmxmono[]hammings\Symuns[]problem%
-\tyxffmxendmono[], that exports a type for unconstrained arrays (those
-not bearing bounds) of positive integers, a package of types and operations
-associated with streams of positive integers, and a procedure to compute
-and deliver the required sequence of values given a maximal output
-value and an array of primes in ascending order. The array type and
-the package of stream types and operations are exported with the procedure
-so that they can be used in forming and manipulating the procedure\rsquo[]s
-inputs and outputs (we have chosen to deliver the sequence of output
-values by appending them to an \tyxffmxmono[]\tyxtstxbf[]in%
-\tyxtstxendbf[]\tyxffmxendmono[] \tyxffmxmono[]\tyxtstxbf[]out%
-\tyxtstxendbf[]\tyxffmxendmono[] parameter which is a stream initially
-passed in as an empty stream). The specification of the %
-\tyxffmxmono[]hammings\Symuns[]problem\tyxffmxendmono[] package is
-shown in Figure \Xref[\def\XrefName{spec-of-hammings-problem}].%
-\NtFoot[]\NtNtpar[]All of the integer values used by, and generated
-in, our solutions to Hamming\rsquo[]s problem are greater than zero,
-except that this assumption of positiveness is not made (since it
-is not required) for the subscripts of objects of the unconstrained
-array type \tyxffmxmono[]positive\Symuns[]array\tyxffmxendmono[].
-It is therefore appropriate to use, as we have done, the subtype %
-\tyxffmxmono[]positive\tyxffmxendmono[], instead of the type %
-\tyxffmxmono[]integer\tyxffmxendmono[], for all of our variables or
-their components; doing so increases the security of the programs
-since, as a consequence, the procedure \tyxffmxmono[]solver%
-\tyxffmxendmono[] can not then be called with scalar actual parameters
-having nonpositive values or composite actual parameters having nonpositive
-components, which if allowed would cause obscure failures. We have
-applied this reasoning to the fullest extent, though in reality the
-necessary security would have been achieved by declaring just the
-formal parameters of \tyxffmxmono[]solver\tyxffmxendmono[] to be (or
-to have components) of subtype \tyxffmxmono[]positive%
-\tyxffmxendmono[], and every other integer variable or component,
-including the components of streams, to be of type %
-\tyxffmxmono[]integer\tyxffmxendmono[]. (One can prove that, if the
-actual parameters in a call to \tyxffmxmono[]solver%
-\tyxffmxendmono[], or their components, are all positive, then all
-integer values generated by the solutions \txtxemph[]will%
-\txtxendemph[] be positive.)\NtEndntpar[]\NtEndfoot[]
-\FgBlock[]
-\Parbox[]
-\FgCap[\def\FgCapId{spec-of-hammings-problem}]Specification of the
-\tyxffmxmono[]hammings\Symuns[]problem\tyxffmxendmono[] package%
-\FgEndcap[]
-\Comp[]\tyxtstxbf[]with\tyxtstxendbf[] streams;
-\tyxtstxbf[]package\tyxtstxendbf[] hammings\Symuns[]problem %
-\tyxtstxbf[]is\tyxtstxendbf[]
-   \tyxtstxbf[]type\tyxtstxendbf[] positive\Symuns[]array %
-\tyxtstxbf[]is\tyxtstxendbf[] \tyxtstxbf[]array\tyxtstxendbf[] (integer %
-\tyxtstxbf[]range\tyxtstxendbf[] \Symlt[]\Symgt[]) \tyxtstxbf[]of%
-\tyxtstxendbf[] positive;
-   \tyxtstxbf[]package\tyxtstxendbf[] positive\Symuns[]streams %
-\tyxtstxbf[]is\tyxtstxendbf[] \tyxtstxbf[]new\tyxtstxendbf[] streams (positive);
-   \tyxtstxbf[]use\tyxtstxendbf[]     positive\Symuns[]streams;
-   \tyxtstxbf[]procedure\tyxtstxendbf[] solver (n       : %
-\tyxtstxbf[]in\tyxtstxendbf[]     positive;
-                     primes  : \tyxtstxbf[]in\tyxtstxendbf[]     positive\Symuns[]array;
-                     outputs : \tyxtstxbf[]in\tyxtstxendbf[] %
-\tyxtstxbf[]out\tyxtstxendbf[] stream);
-\tyxtstxbf[]end\tyxtstxendbf[];\Endcomp[]
-\EndParbox[]
-\FgEndblock[]
-\Endpara[]
-\Para[]The body of the \tyxffmxmono[]hammings\Symuns[]problem%
-\tyxffmxendmono[] package is shown in Figure \Xref[\def\XrefName{body-of-hammings-problem}].
-The functions \tyxffmxmono[]min\tyxffmxendmono[] and %
-\tyxffmxmono[]max\tyxffmxendmono[] are not predefined in Ada, but
-we assume the availability, as a library unit, of a generic package
-named \tyxffmxmono[]min\Symuns[]and\Symuns[]max\tyxffmxendmono[],
-which we instantiate with the subtype \tyxffmxmono[]positive%
-\tyxffmxendmono[]. The result of the instantiation is a package that
-we call \tyxffmxmono[]positive\Symuns[]min\Symuns[]and\Symuns[]max%
-\tyxffmxendmono[]; it exports \tyxffmxmono[]min\tyxffmxendmono[] and
-\tyxffmxmono[]max\tyxffmxendmono[] functions on positive integers.
-We are not concerned here with the implementation of the generic package,
-and for brevity we omit even its specification.
-\FgBlock[\def\FgBlockPlace{H}]
-\Parbox[]
-\FgCap[\def\FgCapId{body-of-hammings-problem}]Body of the %
-\tyxffmxmono[]hammings\Symuns[]problem\tyxffmxendmono[] package (first
-solution)\FgEndcap[]
-\Comp[]\tyxtstxbf[]with\tyxtstxendbf[] min\Symuns[]and\Symuns[]max;
-\tyxtstxbf[]package\tyxtstxendbf[] \tyxtstxbf[]body%
-\tyxtstxendbf[] hammings\Symuns[]problem \tyxtstxbf[]is%
-\tyxtstxendbf[]
-   \tyxtstxbf[]package\tyxtstxendbf[] positive\Symuns[]min\Symuns[]and\Symuns[]max %
-\tyxtstxbf[]is\tyxtstxendbf[] \tyxtstxbf[]new\tyxtstxendbf[] min\Symuns[]and\Symuns[]max (positive);
-   \tyxtstxbf[]use\tyxtstxendbf[]     positive\Symuns[]min\Symuns[]and\Symuns[]max;
-   \tyxtstxbf[]procedure\tyxtstxendbf[] solver (n       : %
-\tyxtstxbf[]in\tyxtstxendbf[]     positive;
-                     primes  : \tyxtstxbf[]in\tyxtstxendbf[]     positive\Symuns[]array;
-                     outputs : \tyxtstxbf[]in\tyxtstxendbf[] %
-\tyxtstxbf[]out\tyxtstxendbf[] stream) \tyxtstxbf[]is%
-\tyxtstxendbf[] \tyxtstxbf[]separate\tyxtstxendbf[];
-\tyxtstxbf[]end\tyxtstxendbf[];\Endcomp[]
-\EndParbox[]
-\FgEndblock[]
-\Endpara[]
-\Para[]A place for the body of the \tyxffmxmono[]solver%
-\tyxffmxendmono[] procedure is held by a \txtxemph[]body stub%
-\txtxendemph[], and the \txtxemph[]proper body\txtxendemph[] of %
-\tyxffmxmono[]solver\tyxffmxendmono[] is made a \txtxemph[]subunit%
-\txtxendemph[] of \tyxffmxmono[]hammings\Symuns[]problem%
-\tyxffmxendmono[]. This allows us to keep our compilation units small.
-The need for that economy is not especially strong now, but the solutions
-to be exhibited subsequently do definitely benefit from this practice.
-The proper body of \tyxffmxmono[]solver\tyxffmxendmono[], as a separate
-compilation unit, is shown in Figure \Xref[\def\XrefName{body-of-solver}].
-\FgBlock[]
-\Parbox[]
-\FgCap[\def\FgCapId{body-of-solver}]Proper body of the %
-\tyxffmxmono[]solver\tyxffmxendmono[] procedure (first solution)%
-\FgEndcap[]
-\Comp[]\tyxtstxbf[]separate\tyxtstxendbf[] (hammings\Symuns[]problem)
-\tyxtstxbf[]procedure\tyxtstxendbf[] solver (n       : %
-\tyxtstxbf[]in\tyxtstxendbf[]     positive;
-                  primes  : \tyxtstxbf[]in\tyxtstxendbf[]     positive\Symuns[]array;
-                  outputs : \tyxtstxbf[]in\tyxtstxendbf[] %
-\tyxtstxbf[]out\tyxtstxendbf[] stream) \tyxtstxbf[]is%
-\tyxtstxendbf[]
-   infinity : \tyxtstxbf[]constant\tyxtstxendbf[] positive := n + 1;
-   pipes    : \tyxtstxbf[]array\tyxtstxendbf[] (primes\rsquo[]range) %
-\tyxtstxbf[]of\tyxtstxendbf[] stream;
-   i        : positive := 1;
-   new\Symuns[]i    : positive;
-\tyxtstxbf[]begin\tyxtstxendbf[]
-   \tyxtstxbf[]while\tyxtstxendbf[] i \Symlt[]= n \tyxtstxbf[]loop%
-\tyxtstxendbf[]
-      append (i, to =\Symgt[] outputs);
-      new\Symuns[]i := infinity;
-      \tyxtstxbf[]for\tyxtstxendbf[] k \tyxtstxbf[]in%
-\tyxtstxendbf[] primes\rsquo[]range \tyxtstxbf[]loop%
-\tyxtstxendbf[]
-         append (i*primes(k), to =\Symgt[] pipes(k));
-         new\Symuns[]i := min(new\Symuns[]i, head(pipes(k)));
-      \tyxtstxbf[]end\tyxtstxendbf[] \tyxtstxbf[]loop%
-\tyxtstxendbf[];
-      i := new\Symuns[]i;
-      \tyxtstxbf[]for\tyxtstxendbf[] k \tyxtstxbf[]in%
-\tyxtstxendbf[] primes\rsquo[]range \tyxtstxbf[]loop%
-\tyxtstxendbf[]
-         \tyxtstxbf[]if\tyxtstxendbf[] head(pipes(k)) = i %
-\tyxtstxbf[]then\tyxtstxendbf[]
-            behead (pipes(k));
-         \tyxtstxbf[]end\tyxtstxendbf[] \tyxtstxbf[]if%
-\tyxtstxendbf[];
-      \tyxtstxbf[]end\tyxtstxendbf[] \tyxtstxbf[]loop%
-\tyxtstxendbf[];
-   \tyxtstxbf[]end\tyxtstxendbf[] \tyxtstxbf[]loop%
-\tyxtstxendbf[];
-\tyxtstxbf[]end\tyxtstxendbf[];\Endcomp[]
-\EndParbox[]
-\FgEndblock[]
-\Endpara[]
-\Para[]The solution shown in Figure \Xref[\def\XrefName{body-of-solver}]
-is somewhat wasteful in that it appends values exceeding %
-\tyxffmxmono[]n\tyxffmxendmono[], the maximal output value, to the
-streams, even though they will never become part of the output sequence;
-they remain in the streams when the main loop terminates. Worse, it
-lacks robustness because the very computation of such values could
-theoretically overflow, bringing the program to a grinding halt. These
-problems could be easily corrected, but the simplicity of the algorithm
-would be obscured by the added detail.\Endpara[]
-\DivEndiv[]
-\DivLiv[]\HdMinLiv[]Second Solution: Processing the Streams in Parallel%
-\HdMinEndiv[]
-\Para[]In each iteration of the main loop, the preceding solution
-cycles through the streams in order. The order of visiting the streams
-is immaterial, of course, and in fact they could be processed in parallel.
-Thus, that solution is actually overspecified.\Endpara[]
-\Para[]For our second solution, a modified proper body of the %
-\tyxffmxmono[]solver\tyxffmxendmono[] procedure is shown in Figure
-\Xref[\def\XrefName{body-of-solver-parallel}],
-\FgBlock[]
-\Parbox[]
-\FgCap[\def\FgCapId{body-of-solver-parallel}]Proper body of the %
-\tyxffmxmono[]solver\tyxffmxendmono[] procedure (second solution)%
-\FgEndcap[]
-\Comp[]\tyxtstxbf[]separate\tyxtstxendbf[] (hammings\Symuns[]problem)
-\tyxtstxbf[]procedure\tyxtstxendbf[] solver (n       : %
-\tyxtstxbf[]in\tyxtstxendbf[]     positive;
-                  primes  : \tyxtstxbf[]in\tyxtstxendbf[]     positive\Symuns[]array;
-                  outputs : \tyxtstxbf[]in\tyxtstxendbf[] %
-\tyxtstxbf[]out\tyxtstxendbf[] stream) \tyxtstxbf[]is%
-\tyxtstxendbf[]
-   \tyxtstxbf[]task\tyxtstxendbf[] \tyxtstxbf[]type%
-\tyxtstxendbf[] stream\Symuns[]processor \tyxtstxbf[]is%
-\tyxtstxendbf[]
-      \tyxtstxbf[]entry\tyxtstxendbf[] install\Symuns[]prime (a\Symuns[]prime : %
-\tyxtstxbf[]in\tyxtstxendbf[] positive);
-   \tyxtstxbf[]end\tyxtstxendbf[];
-   \tyxtstxbf[]task\tyxtstxendbf[] min\Symuns[]finder %
-\tyxtstxbf[]is\tyxtstxendbf[]
-      \tyxtstxbf[]entry\tyxtstxendbf[] bid (a\Symuns[]head : %
-\tyxtstxbf[]in\tyxtstxendbf[] positive);
-      \tyxtstxbf[]entry\tyxtstxendbf[] wait\Symuns[]for\Symuns[]min;
-   \tyxtstxbf[]end\tyxtstxendbf[];
-   infinity : \tyxtstxbf[]constant\tyxtstxendbf[] positive := n + 1;
-   pipes    : \tyxtstxbf[]array\tyxtstxendbf[] (primes\rsquo[]range) %
-\tyxtstxbf[]of\tyxtstxendbf[] stream\Symuns[]processor;
-   i        : positive := 1;
-   \tyxtstxbf[]task\tyxtstxendbf[] \tyxtstxbf[]body%
-\tyxtstxendbf[] stream\Symuns[]processor \tyxtstxbf[]is%
-\tyxtstxendbf[] \tyxtstxbf[]separate\tyxtstxendbf[];
-   \tyxtstxbf[]task\tyxtstxendbf[] \tyxtstxbf[]body%
-\tyxtstxendbf[] min\Symuns[]finder       \tyxtstxbf[]is%
-\tyxtstxendbf[] \tyxtstxbf[]separate\tyxtstxendbf[];
-\tyxtstxbf[]begin\tyxtstxendbf[]
-   \tyxtstxbf[]for\tyxtstxendbf[] k \tyxtstxbf[]in%
-\tyxtstxendbf[] primes\rsquo[]range \tyxtstxbf[]loop%
-\tyxtstxendbf[]
-      pipes(k).install\Symuns[]prime (primes(k));
-   \tyxtstxbf[]end\tyxtstxendbf[] \tyxtstxbf[]loop%
-\tyxtstxendbf[];
-\tyxtstxbf[]end\tyxtstxendbf[];\Endcomp[]
-\EndParbox[]
-\FgEndblock[]
- while the specification and body of the \tyxffmxmono[]hammings\Symuns[]problem%
-\tyxffmxendmono[] package remain unchanged. A separate task is now
-devoted to the processing of each stream. The \tyxffmxmono[]pipes%
-\tyxffmxendmono[] array of streams has been replaced by an array (of
-the same name) whose components are of a task type called %
-\tyxffmxmono[]stream\Symuns[]processor\tyxffmxendmono[]; each task
-in this array declares and processes a single stream, using the corresponding
-prime. There is one additional task, \tyxffmxmono[]min\Symuns[]finder%
-\tyxffmxendmono[], devoted to finding the minimum of the heads of
-all the streams at the appropriate time. Places for the bodies of
-the \tyxffmxmono[]stream\Symuns[]processor\tyxffmxendmono[] task type
-and \tyxffmxmono[]min\Symuns[]finder\tyxffmxendmono[] single task
-are held by body stubs; their proper bodies are made subunits of %
-\tyxffmxmono[]solver\tyxffmxendmono[] and are shown later.%
-\Endpara[]
-\Para[]The \tyxffmxmono[]pipes\tyxffmxendmono[] array of %
-\tyxffmxmono[]stream\Symuns[]processor\tyxffmxendmono[] tasks is created
-as part of the execution of \tyxffmxmono[]solver%
-\tyxffmxendmono[] (specifically, during the elaboration of its declarative
-part). The statement list of \tyxffmxmono[]solver%
-\tyxffmxendmono[] initializes each task with its corresponding prime,
-then waits (at its end) for all the tasks to terminate before returning
-to its caller.\Endpara[]
-\Para[]Each time through their loop, the \tyxffmxmono[]stream\Symuns[]processor%
-\tyxffmxendmono[] tasks bid their respective stream heads as the prospective
-minimum to \tyxffmxmono[]min\Symuns[]finder\tyxffmxendmono[] and then
-wait for \tyxffmxmono[]min\Symuns[]finder\tyxffmxendmono[] to place
-the minimum of the bids in \tyxffmxmono[]i\tyxffmxendmono[] (the variable
-\tyxffmxmono[]i\tyxffmxendmono[] plays the same role as before but
-is now global to all the tasks). The code implementing the behavior
-of a \tyxffmxmono[]stream\Symuns[]processor\tyxffmxendmono[] task
-is shown in Figure \Xref[\def\XrefName{body-of-stream-processor}].
-\FgBlock[\def\FgBlockPlace{H}]
-\Parbox[]
-\FgCap[\def\FgCapId{body-of-stream-processor}]Proper body of the %
-\tyxffmxmono[]stream\Symuns[]processor\tyxffmxendmono[] task type%
-\FgEndcap[]
-\Comp[]\tyxtstxbf[]separate\tyxtstxendbf[] (hammings\Symuns[]problem.solver)
-\tyxtstxbf[]task\tyxtstxendbf[] \tyxtstxbf[]body\tyxtstxendbf[] stream\Symuns[]processor %
-\tyxtstxbf[]is\tyxtstxendbf[]
-   my\Symuns[]prime  : positive;
-   my\Symuns[]stream : stream;
-\tyxtstxbf[]begin\tyxtstxendbf[]
-   \tyxtstxbf[]accept\tyxtstxendbf[] install\Symuns[]prime (a\Symuns[]prime : %
-\tyxtstxbf[]in\tyxtstxendbf[] positive) \tyxtstxbf[]do%
-\tyxtstxendbf[]
-      my\Symuns[]prime := a\Symuns[]prime;
-   \tyxtstxbf[]end\tyxtstxendbf[];
-   \tyxtstxbf[]while\tyxtstxendbf[] i \Symlt[]= n \tyxtstxbf[]loop%
-\tyxtstxendbf[]
-      append (i*my\Symuns[]prime, to =\Symgt[] my\Symuns[]stream);
-      min\Symuns[]finder.bid (head(my\Symuns[]stream));
-      min\Symuns[]finder.wait\Symuns[]for\Symuns[]min;
-      \tyxtstxbf[]if\tyxtstxendbf[] head(my\Symuns[]stream) = i %
-\tyxtstxbf[]then\tyxtstxendbf[]
-         behead (my\Symuns[]stream);
-      \tyxtstxbf[]end\tyxtstxendbf[] \tyxtstxbf[]if%
-\tyxtstxendbf[];
-   \tyxtstxbf[]end\tyxtstxendbf[] \tyxtstxbf[]loop%
-\tyxtstxendbf[];
-\tyxtstxbf[]end\tyxtstxendbf[];\Endcomp[]
-\EndParbox[]
-\FgEndblock[]
-\Endpara[]
-\Para[]The pair of rendezvous used for communication and synchronization
-with \tyxffmxmono[]min\Symuns[]finder\tyxffmxendmono[] acts like a
-\ldquo[]barrier,\rdquo[] preventing the \tyxffmxmono[]stream\Symuns[]processor%
-\tyxffmxendmono[] tasks from moving on to the beheading of their streams
-until all of them have communicated the value of their stream heads
-to \tyxffmxmono[]min\Symuns[]finder\tyxffmxendmono[] and %
-\tyxffmxmono[]min\Symuns[]finder\tyxffmxendmono[] has found the minimum
-of them. The code implementing the behavior of the %
-\tyxffmxmono[]min\Symuns[]finder\tyxffmxendmono[] task is shown in
-Figure \Xref[\def\XrefName{body-of-min-finder}].
-\FgBlock[\def\FgBlockPlace{H}]
-\Parbox[]
-\FgCap[\def\FgCapId{body-of-min-finder}]Proper body of the %
-\tyxffmxmono[]min\Symuns[]finder\tyxffmxendmono[] task%
-\FgEndcap[]
-\Comp[]\tyxtstxbf[]separate\tyxtstxendbf[] (hammings\Symuns[]problem.solver)
-\tyxtstxbf[]task\tyxtstxendbf[] \tyxtstxbf[]body\tyxtstxendbf[] min\Symuns[]finder %
-\tyxtstxbf[]is\tyxtstxendbf[]
-   new\Symuns[]i : positive;
-\tyxtstxbf[]begin\tyxtstxendbf[]
-   \tyxtstxbf[]while\tyxtstxendbf[] i \Symlt[]= n \tyxtstxbf[]loop%
-\tyxtstxendbf[]
-      append(i, to =\Symgt[] outputs);
-      new\Symuns[]i := infinity;
-      \tyxtstxbf[]for\tyxtstxendbf[] k \tyxtstxbf[]in%
-\tyxtstxendbf[] primes\rsquo[]range \tyxtstxbf[]loop%
-\tyxtstxendbf[]
-         \tyxtstxbf[]accept\tyxtstxendbf[] bid (a\Symuns[]head : %
-\tyxtstxbf[]in\tyxtstxendbf[] positive) \tyxtstxbf[]do%
-\tyxtstxendbf[]
-            new\Symuns[]i := min(new\Symuns[]i, a\Symuns[]head);
-         \tyxtstxbf[]end\tyxtstxendbf[];
-      \tyxtstxbf[]end\tyxtstxendbf[] \tyxtstxbf[]loop%
-\tyxtstxendbf[];
-      i := new\Symuns[]i;
-      \tyxtstxbf[]for\tyxtstxendbf[] k \tyxtstxbf[]in%
-\tyxtstxendbf[] primes\rsquo[]range \tyxtstxbf[]loop%
-\tyxtstxendbf[]
-         \tyxtstxbf[]accept\tyxtstxendbf[] wait\Symuns[]for\Symuns[]min;
-      \tyxtstxbf[]end\tyxtstxendbf[] \tyxtstxbf[]loop%
-\tyxtstxendbf[];
-   \tyxtstxbf[]end\tyxtstxendbf[] \tyxtstxbf[]loop%
-\tyxtstxendbf[];
-\tyxtstxbf[]end\tyxtstxendbf[];\Endcomp[]
-\EndParbox[]
-\FgEndblock[]
-\Endpara[]
-\Para[]The second solution cannot seriously be expected to yield any
-significant speedup, since the grains of parallel work between the
-synchronization points are too small in relation to the synchronization
-overhead. The serial bottleneck represented by the barrier has an
-analog in the first solution and does not, by itself, make matters
-worse. The main value of the second solution is to illustrate how
-tasking can be used to replace an unnecessary, deterministic ordering
-by a completely nondeterministic ordering satisfying the relevant
-dataflow properties of the algorithm and nothing else.\NtFoot[]%
-\NtNtpar[]Within the constraints of those dataflow properties, different
-orderings in different runs are caused, of course, by probabilistic
-characteristics of the computing load.\NtEndntpar[]\NtEndfoot[] (The
-for loops in \tyxffmxmono[]min\Symuns[]finder\tyxffmxendmono[] are
-used only to count the number of rendezvous to be performed, not to
-order them; the loop variable is not referenced inside the loops.)%
-\Endpara[]
-\DivEndiv[]
-\DivLiv[]\HdMinLiv[]Third Solution: Novel Use of Concurrency%
-\HdMinEndiv[]
-\Para[]In an idealized implementation of Ada in which a rendezvous
-incurs no overhead, the speedup yielded by the second solution would
-be expected to scale up with the number of primes; if there are more
-processors than primes, the surplus processors would not be exploited.%
-\NtFoot[]\NtNtpar[]Well, almost; one of them would execute %
-\tyxffmxmono[]min\Symuns[]finder\tyxffmxendmono[].\NtEndntpar[]%
-\NtEndfoot[] The radically different approach to be described next
-is capable of being scaled up in proportion to an independent parameter;
-it can therefore always be made to use all available processors. (We
-save for the fourth solution the details of the actual scaling up
-and present here the basic algorithm.)\Endpara[]
-\Para[]Our third solution uses a single recirculating stream of future
-output values; the stream is recirculating because some of the values
-that are removed from its head are put back on the stream at its tail.
-In each iteration of the main loop, the value at the head of the stream
-is removed and placed in the \tyxffmxmono[]outputs%
-\tyxffmxendmono[] stream; it is also used to trigger the generation,
-by another task (called \tyxffmxmono[]products\Symuns[]generator%
-\tyxffmxendmono[]), of a sequence of products of itself and all the
-primes. Meanwhile\EmDash[]that is, as the products are being generated\EmDash[]the
-remainder of the recirculating stream of future output values is read
-and merged with the stream of products as they become available (both
-streams are in ascending order), with the resulting sequence of values
-being directed back to the recirculating stream (i.e., appended to
-its tail).\Endpara[]
-\Para[]In this solution, in contrast to the earlier ones, we do not
-generate any products greater than \tyxffmxmono[]n%
-\tyxffmxendmono[]. It is convenient to use the constant %
-\tyxffmxmono[]infinity\tyxffmxendmono[], defined as %
-\tyxffmxmono[]n+1\tyxffmxendmono[] and previously used for a different
-purpose, as an end-marker both for the stream of products and for
-the recirculating stream of future outputs (where it separates the
-last value produced by one iteration from the first value produced
-by the next). The recirculating stream is initialized to a 1 followed
-by an end-marker; it grows and eventually shrinks in length with succeeding
-iterations, and the algorithm terminates when the recirculating stream
-is reduced to just the end-marker (i.e., when the first value read
-from the recirculating stream in an iteration of the main loop is
-the end-marker). The dataflow characteristics of this algorithm are
-depicted in Figure \Xref[\def\XrefName{data-flow-diagram}].
-\FgBlock[\def\FgBlockPlace{H}]
-\FgCap[\def\FgCapId{data-flow-diagram}]Dataflow in the novel algorithm
-for solving Hamming\rsquo[]s problem\FgEndcap[]
-\PreProcFgGfx\FgGfx[\FgGfxHt=230.44pt \FgGfxWd=510.85pt \def\FgGfxPath{salishan.try12.book}\def\FgGfxCache{salishan.try12.book}\FgGfxX=0.00pt \FgGfxY=0.00pt \def\FgGfxProc{PubDraw}\FgGfxMag=80 \def\FgGfxFilename{data-flow.vec}]
-\FgEndblock[]
-\Endpara[]
-\Para[] The \tyxffmxmono[]products\Symuns[]generator%
-\tyxffmxendmono[] task proceeds at its own pace and could either generate
-products well before they are needed (in which case they remain in
-the \tyxffmxmono[]products\tyxffmxendmono[] stream until needed) or
-generate them so slowly that the \tyxffmxmono[]products%
-\tyxffmxendmono[] stream would be empty when a product is needed from
-it. Therefore the stream abstractions previously assumed are inadequate
-for this application; the fact that the \tyxffmxmono[]products%
-\tyxffmxendmono[] stream is written and read by different tasks should
-be a clue to that inadequacy. We now require that a task trying to
-read a stream that happens to be empty be suspended until some other
-task writes to that stream. Streams of this type will be called \ldquo[]buffers\rdquo[]
-to distinguish them from the earlier kind. Indeed, we now assume the
-availability, as a library unit, of a generic package named %
-\tyxffmxmono[]buffers\tyxffmxendmono[] that provides an abstract data
-type called \tyxffmxmono[]buffer\tyxffmxendmono[] complete with appropriate
-operations on objects of that type. Since we need buffers of positive
-integers, we instantiate the generic package \tyxffmxmono[]buffers%
-\tyxffmxendmono[] with the subtype \tyxffmxmono[]positive%
-\tyxffmxendmono[] to obtain a package that we call %
-\tyxffmxmono[]positive\Symuns[]buffers\tyxffmxendmono[]; its %
-\tyxffmxmono[]buffer\tyxffmxendmono[] type is exactly what we seek.
- As we did with streams, we assume that the initial state of an object
-of type \tyxffmxmono[]buffer\tyxffmxendmono[] is \ldquo[]empty,\rdquo[]
-allowing us to dispense with explicit initialization of buffers. For
-brevity, we omit the body and even the specification of the generic
-package. We remark, however, that it is convenient to combine the
-previous \tyxffmxmono[]head\tyxffmxendmono[] and \tyxffmxmono[]behead%
-\tyxffmxendmono[] operations into a single procedure called %
-\tyxffmxmono[]read\tyxffmxendmono[], which waits for the given buffer
-to become nonempty, then removes and delivers the item at its head.
-We call the buffer analog of \tyxffmxmono[]append%
-\tyxffmxendmono[], to keep our abstractions separate, %
-\tyxffmxmono[]write\tyxffmxendmono[]. Finally, we note that the implementation
-of \tyxffmxmono[]buffers\tyxffmxendmono[] will now surely use tasks
-to achieve the desired suspension of the caller of %
-\tyxffmxmono[]read\tyxffmxendmono[] when required; indeed, the type
-\tyxffmxmono[]buffer\tyxffmxendmono[] can be implemented as a task
-type whose behavior is that of a monitor.\Endpara[]
-\Para[]In the third solution, we retain the use of streams only for
-the outputs of \tyxffmxmono[]solver\tyxffmxendmono[] and use buffers
-elsewhere. In theory, the recirculating \ldquo[]stream\rdquo[] could
-indeed be a stream instead of a buffer, since it is read and written
-by the same task; we have chosen to realize it as a buffer, however,
-in anticipation of the fourth solution (in which the analogous object
-\txtxemph[]must\txtxendemph[] be a buffer), so as to avoid accentuating
-nonessential differences between the current solution and that variation.
-As in the second solution, the specification of the %
-\tyxffmxmono[]hammings\Symuns[]problem\tyxffmxendmono[] package remains
-unchanged, but this time we make a slight change in its body: for
-purely stylistic reasons, that is where we choose to instantiate the
-\tyxffmxmono[]buffers\tyxffmxendmono[] generic package. The revised
-body of the \tyxffmxmono[]hammings\Symuns[]problem%
-\tyxffmxendmono[] package is shown in Figure \Xref[\def\XrefName{body-of-hammings-problem-novel}].
-\FgBlock[\def\FgBlockPlace{H}]
-\Parbox[]
-\FgCap[\def\FgCapId{body-of-hammings-problem-novel}]Body of the %
-\tyxffmxmono[]hammings\Symuns[]problem\tyxffmxendmono[] package (third
-solution)\FgEndcap[]
-\Comp[]\tyxtstxbf[]with\tyxtstxendbf[] min\Symuns[]and\Symuns[]max, buffers;
-\tyxtstxbf[]package\tyxtstxendbf[] \tyxtstxbf[]body%
-\tyxtstxendbf[] hammings\Symuns[]problem \tyxtstxbf[]is%
-\tyxtstxendbf[]
-   \tyxtstxbf[]package\tyxtstxendbf[] positive\Symuns[]min\Symuns[]and\Symuns[]max %
-\tyxtstxbf[]is\tyxtstxendbf[] \tyxtstxbf[]new\tyxtstxendbf[] min\Symuns[]and\Symuns[]max (positive);
-   \tyxtstxbf[]package\tyxtstxendbf[] positive\Symuns[]buffers     %
-\tyxtstxbf[]is\tyxtstxendbf[] \tyxtstxbf[]new\tyxtstxendbf[] buffers (positive);
-   \tyxtstxbf[]use\tyxtstxendbf[]     positive\Symuns[]min\Symuns[]and\Symuns[]max, positive\Symuns[]buffers;
-   \tyxtstxbf[]procedure\tyxtstxendbf[] solver (n       : %
-\tyxtstxbf[]in\tyxtstxendbf[]     positive;
-                     primes  : \tyxtstxbf[]in\tyxtstxendbf[]     positive\Symuns[]array;
-                     outputs : \tyxtstxbf[]in\tyxtstxendbf[] %
-\tyxtstxbf[]out\tyxtstxendbf[] stream) \tyxtstxbf[]is%
-\tyxtstxendbf[] \tyxtstxbf[]separate\tyxtstxendbf[];
-\tyxtstxbf[]end\tyxtstxendbf[];\Endcomp[]
-\EndParbox[]
-\FgEndblock[]
-\Endpara[]
-\Para[]The revised proper body of the \tyxffmxmono[]solver%
-\tyxffmxendmono[] procedure is shown in Figure \Xref[\def\XrefName{body-of-solver-novel}].
-\FgBlock[]
-\Parbox[]
-\FgCap[\def\FgCapId{body-of-solver-novel}]Proper body of the %
-\tyxffmxmono[]solver\tyxffmxendmono[] procedure (third solution)%
-\FgEndcap[]
-\Comp[]\tyxtstxbf[]separate\tyxtstxendbf[] (hammings\Symuns[]problem)
-\tyxtstxbf[]procedure\tyxtstxendbf[] solver (n       : %
-\tyxtstxbf[]in\tyxtstxendbf[]     positive;
-                  primes  : \tyxtstxbf[]in\tyxtstxendbf[]     positive\Symuns[]array;
-                  outputs : \tyxtstxbf[]in\tyxtstxendbf[] %
-\tyxtstxbf[]out\tyxtstxendbf[] stream) \tyxtstxbf[]is%
-\tyxtstxendbf[]
-   infinity : \tyxtstxbf[]constant\tyxtstxendbf[] positive := n + 1;
-   recirc   : buffer;
-   i        : positive;
-\tyxtstxbf[]begin\tyxtstxendbf[]
-   write (1,        to =\Symgt[] recirc);
-   write (infinity, to =\Symgt[] recirc);
-   \tyxtstxbf[]loop\tyxtstxendbf[]
-      read   (i, from =\Symgt[] recirc);
-   \tyxtstxbf[]exit\tyxtstxendbf[] \tyxtstxbf[]when%
-\tyxtstxendbf[] i = infinity;
-      append (i, to   =\Symgt[] outputs);
-      \tyxtstxbf[]declare\tyxtstxendbf[]
-         j, p     : positive;
-         products : buffer;
-         \tyxtstxbf[]task\tyxtstxendbf[] products\Symuns[]generator;
-         \tyxtstxbf[]task\tyxtstxendbf[] \tyxtstxbf[]body%
-\tyxtstxendbf[] products\Symuns[]generator \tyxtstxbf[]is%
-\tyxtstxendbf[]
-         \tyxtstxbf[]begin\tyxtstxendbf[]
-            \tyxtstxbf[]for\tyxtstxendbf[] k \tyxtstxbf[]in%
-\tyxtstxendbf[] primes\rsquo[]range \tyxtstxbf[]loop%
-\tyxtstxendbf[]
-            \tyxtstxbf[]exit\tyxtstxendbf[] \tyxtstxbf[]when%
-\tyxtstxendbf[] i \Symgt[] n/primes(k);
-               write (i*primes(k), to =\Symgt[] products);
-            \tyxtstxbf[]end\tyxtstxendbf[] \tyxtstxbf[]loop%
-\tyxtstxendbf[];
-            write (infinity, to =\Symgt[] products);
-         \tyxtstxbf[]end\tyxtstxendbf[];
-      \tyxtstxbf[]begin\tyxtstxendbf[]
-         read (j, from =\Symgt[] recirc);
-         read (p, from =\Symgt[] products);
-         \tyxtstxbf[]loop\tyxtstxendbf[]
-            \tyxtstxbf[]if\tyxtstxendbf[]    j \Symlt[] p %
-\tyxtstxbf[]then\tyxtstxendbf[]
-               write (j, to   =\Symgt[] recirc);
-               read  (j, from =\Symgt[] recirc);
-            \tyxtstxbf[]elsif\tyxtstxendbf[] j \Symgt[] p %
-\tyxtstxbf[]then\tyxtstxendbf[]
-               write (p, to   =\Symgt[] recirc);
-               read  (p, from =\Symgt[] products);
-            \tyxtstxbf[]else\tyxtstxendbf[]
-               write (j, to   =\Symgt[] recirc);
-         \tyxtstxbf[]exit\tyxtstxendbf[] \tyxtstxbf[]when%
-\tyxtstxendbf[] j = infinity;
-               read  (j, from =\Symgt[] recirc);
-               read  (p, from =\Symgt[] products);
-            \tyxtstxbf[]end\tyxtstxendbf[] \tyxtstxbf[]if%
-\tyxtstxendbf[];
-         \tyxtstxbf[]end\tyxtstxendbf[] \tyxtstxbf[]loop%
-\tyxtstxendbf[];
-      \tyxtstxbf[]end\tyxtstxendbf[];
-   \tyxtstxbf[]end\tyxtstxendbf[] \tyxtstxbf[]loop%
-\tyxtstxendbf[];
-\tyxtstxbf[]end\tyxtstxendbf[];\Endcomp[]
-\EndParbox[]
-\FgEndblock[]
- The \tyxffmxmono[]products\Symuns[]generator\tyxffmxendmono[] task
-is created and subsequently terminates, when it
-\TyPbrkNewp[]
- reaches the end of its execution, each time through the main loop.
-With a slight redesign, we could arrange to create it just once, enclose
-its processing within a loop, synchronize that loop with the main
-loop in the \tyxffmxmono[]solver\tyxffmxendmono[] procedure, and make
-it terminate at the appropriate time. That redesign would require
-the use of a rendezvous for the synchronization, and distributed termination
-for the \tyxffmxmono[]products\Symuns[]generator%
-\tyxffmxendmono[] task. But since simplicity is more desirable than
-efficiency in these solutions, we have chosen the method having conceptually
-simpler semantics.\Endpara[]
-\DivEndiv[]
-\DivLiv[]\HdMinLiv[]Fourth Solution: Dataflow Loop Unrolling%
-\HdMinEndiv[]
-\Para[]The technique of \ldquo[]loop unrolling\rdquo[] can be applied
-in a unique way to the dataflow loop in Figure \Xref[\def\XrefName{data-flow-diagram}]
-by considering all the processing of  values between the moment they
-are removed from the recirculating stream and the moment they are
-put back in it to be a single \ldquo[]stage\rdquo[] of processing;
-by encapsulating a stage of processing in a task; by replicating that
-task any number of times; and by interposing buffers (instead of streams)
-between the tasks\EmDash[]that is, between the stages. By spreading
-the processing over a larger number of tasks, the result, whose dataflow
-characteristics are shown in Figure
-\FgBlock[\def\FgBlockPlace{H}]
-\FgCap[\def\FgCapId{unrolled-data-flow-diagram}]Dataflow in the novel
-algorithm for solving Hamming\rsquo[]s problem, with loop unrolling%
-\FgEndcap[]
-\PreProcFgGfx\FgGfx[\FgGfxHt=376.09pt \FgGfxWd=491.72pt \def\FgGfxPath{salishan.try12.book}\def\FgGfxCache{salishan.try12.book}\FgGfxX=0.00pt \FgGfxY=0.00pt \def\FgGfxProc{PubDraw}\FgGfxMag=80 \def\FgGfxFilename{unrolled-data-flow.vec}]
-\FgEndblock[]
- \Xref[\def\XrefName{unrolled-data-flow-diagram}], achieves potentially
-greater parallelism\EmDash[]principally because several streams of
-products can be generated and merged with the recirculating stream
-of future outputs concurrently. It should be noted that the \ldquo[]recirculating
-stream\rdquo[] of future output values is now spread out over the
-whole dataflow loop, with some values in each intertask buffer and
-some in local variables of each task, and with only one end-marker
-located somewhere around the loop. Although many tasks now append
-to the \tyxffmxmono[]outputs\tyxffmxendmono[] stream, only one at
-a time does so as the \ldquo[]front\rdquo[] of the stream of future
-outputs advances from one stage to the next, and thus no synchronization
-problems arise from this behavior.\Endpara[]
-\Para[]The code for the fourth solution, the variant of the novel
-algorithm with dataflow loop unrolling, is split between two figures.
-Figure \Xref[\def\XrefName{body-of-solver-novel-unrolled}]
-\FgBlock[\def\FgBlockPlace{H}]
-\Parbox[]
-\FgCap[\def\FgCapId{body-of-solver-novel-unrolled}]Proper body of
-the \tyxffmxmono[]solver\tyxffmxendmono[] procedure (fourth solution)%
-\FgEndcap[]
-\Comp[]\tyxtstxbf[]separate\tyxtstxendbf[] (hammings\Symuns[]problem)
-\tyxtstxbf[]procedure\tyxtstxendbf[] solver (n, m    : %
-\tyxtstxbf[]in\tyxtstxendbf[]     positive;
-                  primes  : \tyxtstxbf[]in\tyxtstxendbf[]     positive\Symuns[]array;
-                  outputs : \tyxtstxbf[]in\tyxtstxendbf[] %
-\tyxtstxbf[]out\tyxtstxendbf[] stream) \tyxtstxbf[]is%
-\tyxtstxendbf[]
-   \tyxtstxbf[]task\tyxtstxendbf[] \tyxtstxbf[]type%
-\tyxtstxendbf[] stage \tyxtstxbf[]is\tyxtstxendbf[]
-      \tyxtstxbf[]entry\tyxtstxendbf[] identify\Symuns[]self (k : %
-\tyxtstxbf[]in\tyxtstxendbf[] positive);
-   \tyxtstxbf[]end\tyxtstxendbf[];
-   infinity : \tyxtstxbf[]constant\tyxtstxendbf[] positive := n + 1;
-   stages   : \tyxtstxbf[]array\tyxtstxendbf[] (1 .. m) %
-\tyxtstxbf[]of\tyxtstxendbf[] stage;
-   sbuffers : \tyxtstxbf[]array\tyxtstxendbf[] (1 .. m) %
-\tyxtstxbf[]of\tyxtstxendbf[] buffer;
-   done     : \tyxtstxbf[]array\tyxtstxendbf[] (1 .. m) %
-\tyxtstxbf[]of\tyxtstxendbf[] boolean := (\tyxtstxbf[]others%
-\tyxtstxendbf[] =\Symgt[] false);
-   \tyxtstxbf[]task\tyxtstxendbf[] \tyxtstxbf[]body%
-\tyxtstxendbf[] stage \tyxtstxbf[]is\tyxtstxendbf[] \tyxtstxbf[]separate%
-\tyxtstxendbf[];
-\tyxtstxbf[]begin\tyxtstxendbf[]
-   write (1,        to =\Symgt[] sbuffers(1));
-   write (infinity, to =\Symgt[] sbuffers(1));
-   \tyxtstxbf[]for\tyxtstxendbf[] k \tyxtstxbf[]in%
-\tyxtstxendbf[] stages\rsquo[]range \tyxtstxbf[]loop%
-\tyxtstxendbf[]
-      stages(k).identify\Symuns[]self (k);
-   \tyxtstxbf[]end\tyxtstxendbf[] \tyxtstxbf[]loop%
-\tyxtstxendbf[];
-\tyxtstxbf[]end\tyxtstxendbf[];\Endcomp[]
-\EndParbox[]
-\FgEndblock[]
- shows the revised proper body of the \tyxffmxmono[]solver%
-\tyxffmxendmono[] procedure, in which the body of the %
-\tyxffmxmono[]stage\tyxffmxendmono[] task type is represented by a
-body stub. The proper body of \tyxffmxmono[]stage%
-\tyxffmxendmono[] is shown in Figure \Xref[\def\XrefName{body-of-stage}].
-\FgBlock[]
-\Parbox[]
-\FgCap[\def\FgCapId{body-of-stage}]Proper body of the %
-\tyxffmxmono[]stage\tyxffmxendmono[] task type\FgEndcap[]
-\Comp[]\tyxtstxbf[]separate\tyxtstxendbf[] (hammings\Symuns[]problem.solver)
-\tyxtstxbf[]task\tyxtstxendbf[] \tyxtstxbf[]body\tyxtstxendbf[] stage %
-\tyxtstxbf[]is\tyxtstxendbf[]
-   i, self, successor : positive;
-\tyxtstxbf[]begin\tyxtstxendbf[]
-   \tyxtstxbf[]accept\tyxtstxendbf[] identify\Symuns[]self (k : %
-\tyxtstxbf[]in\tyxtstxendbf[] positive) \tyxtstxbf[]do%
-\tyxtstxendbf[]
-      self := k;
-   \tyxtstxbf[]end\tyxtstxendbf[];
-   successor := self \tyxtstxbf[]mod\tyxtstxendbf[] m + 1;
-   \tyxtstxbf[]loop\tyxtstxendbf[]
-      read   (i, from =\Symgt[] sbuffer(self));
-   \tyxtstxbf[]exit\tyxtstxendbf[] \tyxtstxbf[]when%
-\tyxtstxendbf[] i = infinity;
-      append (i, to   =\Symgt[] outputs);
-      \tyxtstxbf[]declare\tyxtstxendbf[]
-         j, p     : positive;
-         products : buffer;
-         \tyxtstxbf[]task\tyxtstxendbf[] products\Symuns[]generator;
-         \tyxtstxbf[]task\tyxtstxendbf[] \tyxtstxbf[]body%
-\tyxtstxendbf[] products\Symuns[]generator \tyxtstxbf[]is%
-\tyxtstxendbf[]
-         \tyxtstxbf[]begin\tyxtstxendbf[]
-            \tyxtstxbf[]for\tyxtstxendbf[] k \tyxtstxbf[]in%
-\tyxtstxendbf[] primes\rsquo[]range \tyxtstxbf[]loop%
-\tyxtstxendbf[]
-            \tyxtstxbf[]exit\tyxtstxendbf[] \tyxtstxbf[]when%
-\tyxtstxendbf[] i \Symgt[] n/primes(k);
-               write (i*primes(k), to =\Symgt[] products);
-            \tyxtstxbf[]end\tyxtstxendbf[] \tyxtstxbf[]loop%
-\tyxtstxendbf[];
-            write (infinity, to =\Symgt[] products);
-         \tyxtstxbf[]end\tyxtstxendbf[];
-      \tyxtstxbf[]begin\tyxtstxendbf[]
-         read (j, from =\Symgt[] sbuffer(self));
-         read (p, from =\Symgt[] products);
-         \tyxtstxbf[]loop\tyxtstxendbf[]
-            \tyxtstxbf[]if\tyxtstxendbf[]    j \Symlt[] p %
-\tyxtstxbf[]then\tyxtstxendbf[]
-               write (j, to   =\Symgt[] sbuffer(successor));
-               read  (j, from =\Symgt[] sbuffer(self));
-            \tyxtstxbf[]elsif\tyxtstxendbf[] j \Symgt[] p %
-\tyxtstxbf[]then\tyxtstxendbf[]
-               write (p, to   =\Symgt[] sbuffer(successor));
-               read  (p, from =\Symgt[] products);
-            \tyxtstxbf[]else\tyxtstxendbf[]
-               write (j, to   =\Symgt[] sbuffer(successor));
-         \tyxtstxbf[]exit\tyxtstxendbf[] \tyxtstxbf[]when%
-\tyxtstxendbf[] j = infinity;
-               read  (j, from =\Symgt[] sbuffer(self));
-               read  (p, from =\Symgt[] products);
-            \tyxtstxbf[]end\tyxtstxendbf[] \tyxtstxbf[]if%
-\tyxtstxendbf[];
-         \tyxtstxbf[]end\tyxtstxendbf[] \tyxtstxbf[]loop%
-\tyxtstxendbf[];
-      \tyxtstxbf[]end\tyxtstxendbf[];
-   \tyxtstxbf[]end\tyxtstxendbf[] \tyxtstxbf[]loop%
-\tyxtstxendbf[];
-   done(self) := true;
-   \tyxtstxbf[]if\tyxtstxendbf[] \tyxtstxbf[]not\tyxtstxendbf[] done(successor) %
-\tyxtstxbf[]then\tyxtstxendbf[]
-      write (infinity, to =\Symgt[] sbuffer(successor));
-   \tyxtstxbf[]end\tyxtstxendbf[] \tyxtstxbf[]if\tyxtstxendbf[];
-\tyxtstxbf[]end\tyxtstxendbf[];\Endcomp[]
-\EndParbox[]
-\FgEndblock[]
-\Endpara[]
-\Para[]We have given \tyxffmxmono[]solver\tyxffmxendmono[] an extra
-parameter, \tyxffmxmono[]m\tyxffmxendmono[], which is the depth of
-the loop unrolling (number of stages); to save space, we omit showing
-the trivial change in the specification and body of the %
-\tyxffmxmono[]hammings\Symuns[]problem\tyxffmxendmono[] package necessitated
-by this addition. Ideally, the value of \tyxffmxmono[]m%
-\tyxffmxendmono[] should be increased in proportion to the number
-of processors available, at a rate that is probably best determined
-empirically (it depends on how much of a processor\rsquo[]s power
-is consumed by the tasks of each stage, among other things).%
-\Endpara[]
-\Para[]In this solution, most of the work is done by the dependent
-tasks of \tyxffmxmono[]solver\tyxffmxendmono[]. After \ldquo[]priming\rdquo[]
-the first stage and then identifying to each stage its position in
-the dataflow loop, \tyxffmxmono[]solver\tyxffmxendmono[] waits (at
-its end) for its dependent tasks to terminate before returning to
-its caller; when it finally does so, the \tyxffmxmono[]outputs%
-\tyxffmxendmono[] stream will have been completed.\Endpara[]
-\Para[]As shown by Figure \Xref[\def\XrefName{body-of-stage}], each
-stage\rsquo[]s first action is to receive its position in
-\TyPbrkNewp[]
- the dataflow loop from \tyxffmxmono[]solver\tyxffmxendmono[]. It
-then computes the position of its successor. These positions are,
-of course, indices in the arrays declared by \tyxffmxmono[]solver%
-\tyxffmxendmono[], so that the successor of the last component in
-each of these arrays is the first component. Each \tyxffmxmono[]stage%
-\tyxffmxendmono[] uses its own index and that of its successor to
-determine which intertask buffer is its input buffer and which is
-its output buffer.\Endpara[]
-\Para[]When a stage reads the end-marker as the first item from its
-input buffer, in an execution of its main loop, it sets its own component
-of the \tyxffmxmono[]done\tyxffmxendmono[] array to %
-\tyxffmxmono[]true\tyxffmxendmono[], propagates the end-marker if
-required, and then terminates. Propagation of the end-marker from
-one stage to its successor is required if the successor has not yet
-read an end-marker as the first item from \txtxemph[]its%
-\txtxendemph[] input buffer, as indicated by the successor\rsquo[]s
-component of the \tyxffmxmono[]done\tyxffmxendmono[] array. Were the
-end-marker not propagated in this way, stages would deadlock waiting
-for input that would never arrive, and \tyxffmxmono[]solver%
-\tyxffmxendmono[] would never terminate. But, after the end-marker
-(not preceded by any future outputs) has made its way around the dataflow
-loop once, all of the stages will have terminated, and there will
-thus be no need to propagate it further.\Endpara[]
-\Para[]Care has been taken to ensure that the fourth solution will
-work for all values of \tyxffmxmono[]m\tyxffmxendmono[]\EmDash[]in
-particular, even for the value 1. In that case, the successor of a
-stage is itself, and changes made by the stage to its \ldquo[]right-hand\rdquo[]
-environment are immediately seen as having an effect on its \ldquo[]left-hand\rdquo[]
-environment (and vice versa). The similarities between Figures %
-\Xref[\def\XrefName{body-of-stage}] and \Xref[\def\XrefName{body-of-solver-novel}]
-suggest that a further level of subprogram abstraction would have
-been appropriate.\Endpara[]
-\DivEndiv[]
-\DivEndiii[]
-\DivLiii[]\HdMjLiii[]The Paraffins Problem\HdMjEndiii[]
-\Para[]The chemical formula for paraffin molecules is \InlEqn[]\LmthEqn[]
-{\rm C_{
-{\mit i}}H_{2
-{\mit i}+1}}
-\LmthEndeqn[]%
-\EndInlEqn[]. The problem is as follows: Given an integer %
-\InlEqn[]\LmthEqn[]n
-\LmthEndeqn[]\EndInlEqn[], output\EmDash[]in order of increasing size\EmDash[]structural
-representations of all paraffin molecules for \InlEqn[]\LmthEqn[]i
-\leq n
-\LmthEndeqn[]%
-\EndInlEqn[], including all isomers but no duplicates.\Endpara[]
-\Para[]The paraffins problem was designed to reveal the strengths
-of applicative languages. Turner\rsquo[]s original solution %
-\Cit[\def\CitId{Turner:Paraffins}]\Endcit[] in the applicative language
-KRC makes extensive use of set abstraction and higher-order functions
-to produce a compact and elegant program at the cost of some inefficiency.
-His program was designed to produce all paraffin molecules of a given
-size by attaching paraffin radicals of appropriate sizes to a leading
-carbon atom without regard, initially, to the fact that this simple
-process yields many different representations (different orientations)
-of each of the distinct paraffin isomers. Since the problem calls
-for producing only one representation of each isomer, Turner\rsquo[]s
-solution filters out the duplicates. As each new paraffin molecule
-is generated, it is tested for distinctness from all previously retained
-molecules. The test for distinctness consists of checking each of
-the previously retained molecules for membership in the set of all
-structurally equivalent reorientations of the newly generated molecule.
-The latter set is obtained on the fly by computing the closure of
-the set containing the newly generated molecule under various equivalence-preserving
-transformations (rotations, inversions, and swapping of the paraffin
-radicals attached to each of the molecule\rsquo[]s carbon atoms).
-For this process to be workable, implicit or explicit garbage collection
-must be at work. The KRC solution is concise in part because garbage
-collection is implicit and in part because no premium is placed on
-avoiding the recomputation of a previously computed closure set each
-time a new duplicate is found. The strategy adopted by Turner also
-was influenced by another feature of KRC\EmDash[]lazy evaluation\EmDash[]which
-at least partially reclaims some of the lost efficiency by deferring
-the computation of a set element until it is needed (a duplicate is
-typically found when its closure set is still incomplete).%
-\Endpara[]
-\Para[]A programmer faced with solving this problem in a language
-not having the powerful and convenient features of KRC (or other applicative
-languages) is strongly motivated to forgo Turner\rsquo[]s solution\EmDash[]if
-programming explicit garbage collection is unappealing, and if strict
-evaluation and repeated computation are unacceptably inefficient\EmDash[]and
-instead search for a strategy that generates paraffin molecules so
-that duplicates are avoided from the outset. The Ada solution, like
-most of the others in this book, follows such a strategy.%
-\NtFoot[]\NtNtpar[]Actually, Ada \txtxemph[]allows\txtxendemph[] for
-implicit garbage collection, but it also provides mechanisms for explicit
-freeing of dynamically allocated storage. Had we found implicit garbage
-collection to be routinely implemented, we might have been motivated
-to obtain a solution in the spirit of Turner\rsquo[]s; in reality,
-it has only rarely been implemented in Ada systems. Ada solutions
-significantly different from the present one would have required more
-storage or more time, and certainly more code.\NtEndntpar[]%
-\NtEndfoot[]\Endpara[]
-\Para[]A paraffin molecule can be regarded as a free tree (see %
-\Cit[\def\CitId{Knuth:Vol1}]\Endcit[], \Nobr[]pp. 362\EnDash[]363%
-\Endnobr[]) whose vertices correspond to the carbon atoms and whose
-edges correspond to the carbon-carbon bonds. The distinct paraffin
-isomers of size \InlEqn[]\LmthEqn[]i
-\LmthEndeqn[]\EndInlEqn[]\EmDash[]that is, having %
-\InlEqn[]\LmthEqn[]i
-\LmthEndeqn[]\EndInlEqn[] carbon atoms\EmDash[]therefore correspond to
-the structurally distinct free trees having \InlEqn[]\LmthEqn[]i
-\LmthEndeqn[]%
-\EndInlEqn[] vertices. Our program represents paraffin molecules as
-oriented, ordered trees (whose vertices we refer to here as nodes)\EmDash[]not
-as free trees\EmDash[]and the essence of our strategy for avoiding
-duplicates lies in the mapping between the vertices of the free-tree
-representation of a paraffin molecule and the nodes of its corresponding
-representation as an oriented, ordered tree in the program.%
-\Endpara[]
-\Para[]It is apparent that the unordered neighbors of a vertex of
-the free-tree representation will become ordered subnodes of the node
-to which it is mapped in the representation used in the program. Varying
-the order of the subnodes results in different representations of
-the same paraffin molecule\EmDash[]that is, in structurally equivalent
-paraffin molecules. We avoid this source of duplicates by using a
-unique (lexicographic) ordering for the subnodes of a node. Note that
-whereas vertices of the free tree may have fewer than four neighbors
-(i.e., when they represent carbon atoms to which some hydrogen atoms
-are attached), the corresponding nodes in the tree in the program
-have either four subnodes (in the case of the root node) or three
-subnodes and an ancestor node (in the case of a node other than the
-root). Also note that some of the subnodes represent hydrogen atoms;
-in the program, the positions at which hydrogen atoms are attached
-to carbon atoms are explicit.\Endpara[]
-\Para[]It is also apparent that the unoriented edges of the free tree
-will become directed links between nodes in the tree in the program
-and that some vertex will be mapped to the root node. Varying the
-vertex that is mapped to the root node again results in different
-representations of the same paraffin molecule. We avoid this source
-of duplicates by appealing to the \txtxemph[]centroid theorem for
-free trees\txtxendemph[] (see \Cit[\def\CitId{Knuth:Vol1}]%
-\Endcit[], \Nobr[]p. 387\Endnobr[]): a free tree of odd size has a
-single centroid (vertex of minimum height, where the height of a vertex
-is the size of its largest subtree), while one of even size has either
-a single centroid or a pair of adjacent centroids. We canonicalize
-the representation of single-centroid paraffin molecules by selecting
-the centroid as the root node in the program tree. In the case of
-double-centroid paraffin molecules, we use as root node a node that
-corresponds not to any carbon atom but to the carbon-carbon bond between
-the centroids. It has exactly two subnodes, corresponding to the two
-centroids; they, of course, are lexicographically ordered as well.%
-\Endpara[]
-\Para[]To summarize, our strategy avoids duplicates by canonically
-selecting root nodes and lexicographically ordering subnodes.%
-\Endpara[]
-\Para[]Odd-sized paraffin molecules and even-sized single-centroid
-paraffin molecules are here called \ldquo[]carbon-centered paraffins,\rdquo[]
-or CCPs; the root nodes of their trees correspond to carbon atoms
-and have four subnodes, each the root of a subtree representing a
-paraffin radical. The four radicals of a CCP of size \InlEqn[]\LmthEqn[]i
-\LmthEndeqn[]%
-\EndInlEqn[] each have size less than or equal to \InlEqn[]\LmthEqn[]
-\left\lfloor {{{i-1} \over {2}}}
-\right\rfloor 
-\LmthEndeqn[]%
-\EndInlEqn[] and total \InlEqn[]\LmthEqn[]i-1
-\LmthEndeqn[]\EndInlEqn[] in size. Even-sized double-centroid
-paraffin molecules are here called \ldquo[]bond-centered paraffins,\rdquo[]
-or BCPs; the root nodes of their trees correspond to carbon-carbon
-bonds and have two subnodes, each the root of a subtree representing
-a paraffin radical. The two radicals of a BCP of size \InlEqn[]\LmthEqn[]i
-\LmthEndeqn[]%
-\EndInlEqn[] each have size exactly equal to \InlEqn[]\LmthEqn[]{{i} \over {2}}
-\LmthEndeqn[]%
-\EndInlEqn[] and therefore total \InlEqn[]\LmthEqn[]i
-\LmthEndeqn[]\EndInlEqn[] in size. For
-their part, the root nodes of paraffin radicals of size %
-\InlEqn[]\LmthEqn[]i
-\LmthEndeqn[]\EndInlEqn[], for \InlEqn[]\LmthEqn[]i>0
-\LmthEndeqn[]\EndInlEqn[], correspond to carbon
-atoms and have three subnodes, each the root of a subtree representing
-a paraffin radical. (Thus, the data structure for paraffin radicals
-is recursive.) The three subradicals of such a paraffin radical each
-have size less than or equal to \InlEqn[]\LmthEqn[]i-1
-\LmthEndeqn[]\EndInlEqn[] and total %
-\InlEqn[]\LmthEqn[]i-1
-\LmthEndeqn[]\EndInlEqn[] in size. A paraffin radical of size 0 is just
-a hydrogen radical; its root node corresponds to a hydrogen atom and
-has no subnodes. In the program, all three kinds of objects are constructed
-by the same process, which amounts to attaching some number\EmDash[]two,
-three, or four\EmDash[]of paraffin radicals of appropriate sizes to
-some other node. Restrictions on the maximum sizes of the attached
-radicals guarantee that the node at the root of a CCP corresponds
-to the centroid, and similarly that the pair of nodes immediately
-descendent from the root of a BCP always correspond to the adjacent
-centroids; this property, together with the lexicographic ordering
-of the attached radicals, guarantees the avoidance of duplicates.%
-\Endpara[]
-\DivLiv[]\HdMinLiv[]Serial Solution\HdMinEndiv[]
-\Para[]For the sake of simplicity, we develop in this section a completely
-serial solution to the paraffins problem; in the next section, we
-discuss the opportunities for parallelism presented by the problem
-and obtain one parallel solution by a straightforward modification
-of a small part of the serial solution.\Endpara[]
-\Para[]At the top level, our serial solution is in the form of a function,
-\tyxffmxmono[]paraffins\tyxffmxendmono[] (shown in Figure %
-\Xref[\def\XrefName{body-of-paraffins-serial}]),
-\FgBlock[]
-\Parbox[]
-\FgCap[\def\FgCapId{body-of-paraffins-serial}]Self-specifying body
-of the \tyxffmxmono[]paraffins\tyxffmxendmono[] function (serial version)%
-\FgEndcap[]
-\Comp[]\tyxtstxbf[]with\tyxtstxendbf[] radicals, molecules;
-\tyxtstxbf[]use\tyxtstxendbf[]  radicals, molecules;
-\tyxtstxbf[]function\tyxtstxendbf[] paraffins (n : positive) %
-\tyxtstxbf[]return\tyxtstxendbf[] array\Symuns[]of\Symuns[]molecule\Symuns[]lists %
-\tyxtstxbf[]is\tyxtstxendbf[]
-   \tyxtstxbf[]type\tyxtstxendbf[] array\Symuns[]of\Symuns[]naturals %
-\tyxtstxbf[]is\tyxtstxendbf[] \tyxtstxbf[]array\tyxtstxendbf[] (positive %
-\tyxtstxbf[]range\tyxtstxendbf[] \Symlt[]\Symgt[]) \tyxtstxbf[]of%
-\tyxtstxendbf[] natural;
-   \tyxtstxbf[]use\tyxtstxendbf[] radical\Symuns[]lists, molecule\Symuns[]lists;
-   r\Symuns[]array : array\Symuns[]of\Symuns[]radical\Symuns[]lists  (0 .. n/2);
-   m\Symuns[]array : array\Symuns[]of\Symuns[]molecule\Symuns[]lists (1 .. n);
-   \tyxtstxbf[]generic\tyxtstxendbf[]
-      \tyxtstxbf[]with\tyxtstxendbf[] \tyxtstxbf[]procedure%
-\tyxtstxendbf[] apply\Symuns[]to\Symuns[]each (tuple : %
-\tyxtstxbf[]in\tyxtstxendbf[] array\Symuns[]of\Symuns[]radicals);
-   \tyxtstxbf[]procedure\tyxtstxendbf[] enum\Symuns[]rad\Symuns[]tuples (p : %
-\tyxtstxbf[]in\tyxtstxendbf[] array\Symuns[]of\Symuns[]naturals);
-   \tyxtstxbf[]procedure\tyxtstxendbf[] enum\Symuns[]rad\Symuns[]tuples (p : %
-\tyxtstxbf[]in\tyxtstxendbf[] array\Symuns[]of\Symuns[]naturals)  %
-\tyxtstxbf[]is\tyxtstxendbf[] \tyxtstxbf[]separate%
-\tyxtstxendbf[];
-   \tyxtstxbf[]procedure\tyxtstxendbf[] generate\Symuns[]radicals\Symuns[]of\Symuns[]size (i : %
-\tyxtstxbf[]in\tyxtstxendbf[] positive) \tyxtstxbf[]is%
-\tyxtstxendbf[] \tyxtstxbf[]separate\tyxtstxendbf[];
-   \tyxtstxbf[]procedure\tyxtstxendbf[] generate\Symuns[]ccps\Symuns[]of\Symuns[]size     (i : %
-\tyxtstxbf[]in\tyxtstxendbf[] positive) \tyxtstxbf[]is%
-\tyxtstxendbf[] \tyxtstxbf[]separate\tyxtstxendbf[];
-   \tyxtstxbf[]procedure\tyxtstxendbf[] generate\Symuns[]bcps\Symuns[]of\Symuns[]size     (i : %
-\tyxtstxbf[]in\tyxtstxendbf[] positive) \tyxtstxbf[]is%
-\tyxtstxendbf[] \tyxtstxbf[]separate\tyxtstxendbf[];
-\tyxtstxbf[]begin\tyxtstxendbf[]
-   append (hydrogen\Symuns[]radical, to =\Symgt[] r\Symuns[]array(0));
-   \tyxtstxbf[]for\tyxtstxendbf[] i \tyxtstxbf[]in%
-\tyxtstxendbf[] 1 .. n/2 \tyxtstxbf[]loop\tyxtstxendbf[]
-      generate\Symuns[]radicals\Symuns[]of\Symuns[]size (i);
-   \tyxtstxbf[]end\tyxtstxendbf[] \tyxtstxbf[]loop%
-\tyxtstxendbf[];
-   \tyxtstxbf[]for\tyxtstxendbf[] i \tyxtstxbf[]in%
-\tyxtstxendbf[] 1 .. n \tyxtstxbf[]loop\tyxtstxendbf[]
-      generate\Symuns[]ccps\Symuns[]of\Symuns[]size (i);
-      \tyxtstxbf[]if\tyxtstxendbf[] i \tyxtstxbf[]mod%
-\tyxtstxendbf[] 2 = 0 \tyxtstxbf[]then\tyxtstxendbf[]
-         generate\Symuns[]bcps\Symuns[]of\Symuns[]size (i);
-      \tyxtstxbf[]end\tyxtstxendbf[] \tyxtstxbf[]if%
-\tyxtstxendbf[];
-   \tyxtstxbf[]end\tyxtstxendbf[] \tyxtstxbf[]loop%
-\tyxtstxendbf[];
-   \tyxtstxbf[]return\tyxtstxendbf[] m\Symuns[]array;
-\tyxtstxbf[]end\tyxtstxendbf[];\Endcomp[]
-\EndParbox[]
-\FgEndblock[]
- that takes a positive integer, \tyxffmxmono[]n\tyxffmxendmono[],
-and returns an array, indexed by the values 1 to \tyxffmxmono[]n%
-\tyxffmxendmono[], whose \InlEqn[]\LmthEqn[]i
-\LmthEndeqn[]\EndInlEqn[]th component is a list
-of the unique paraffin isomers of size \InlEqn[]\LmthEqn[]i
-\LmthEndeqn[]\EndInlEqn[]. The
-function is compiled in the context of some application-dependent
-types for radicals and molecules that are defined in the two library
-packages (\tyxffmxmono[]radicals\tyxffmxendmono[] and %
-\tyxffmxmono[]molecules\tyxffmxendmono[]) named in its context clauses.
-Certainly the function needs some such types; presumably the larger
-application of which the function is a part does, too. (The specifications
-and bodies of the packages of types are shown in Figures \Xref[\def\XrefName{spec-of-radicals}]
-through \Xref[\def\XrefName{body-of-molecules}].) The %
-\tyxffmxmono[]paraffins\tyxffmxendmono[] function first sequentially
-creates, and internally stores in the components of the local array
-\tyxffmxmono[]r\Symuns[]array\tyxffmxendmono[], lists of paraffin
-radicals of sizes 0 to \tyxffmxmono[]n/2\tyxffmxendmono[] (integer
-division in Ada truncates towards zero, which for positive operands
-is equivalent to delivering the floor of the quotient); %
-\tyxffmxmono[]n/2\tyxffmxendmono[] is the size of the largest radical
-that will be needed for a paraffin molecule of size %
-\tyxffmxmono[]n\tyxffmxendmono[]. The radicals are created in order
-of size because smaller radicals are needed for the construction of
-larger ones.\NtFoot[]\NtNtpar[]Our lexicographic ordering is such
-that two radicals are lexicographically ordered if the first is smaller
-than the second or if they are of the same size and the first occurs
-not later than the second on the list of radicals of their common
-size.\NtEndntpar[]\NtEndfoot[] Next, the function sequentially creates
-lists of paraffin molecules of sizes 1 to \tyxffmxmono[]n%
-\tyxffmxendmono[], storing in the \InlEqn[]\LmthEqn[]i
-\LmthEndeqn[]\EndInlEqn[]th component
-of \tyxffmxmono[]m\Symuns[]array\tyxffmxendmono[] the list for size
-\InlEqn[]\LmthEqn[]i
-\LmthEndeqn[]\EndInlEqn[]\EmDash[]first the CCPs, and then (for even sizes)
-the BCPs. Finally, it returns \tyxffmxmono[]m\Symuns[]array%
-\tyxffmxendmono[]. (The contents of the function are further discussed
-later.)\Endpara[]
-\Para[]Let\rsquo[]s look at the packages that declare the problem-dependent
-types used in the solution. The specification of the package %
-\tyxffmxmono[]radicals\tyxffmxendmono[] is shown in Figure %
-\Xref[\def\XrefName{spec-of-radicals}].
-\FgBlock[\def\FgBlockPlace{H}]
-\Parbox[]
-\FgCap[\def\FgCapId{spec-of-radicals}]Specification of the %
-\tyxffmxmono[]radicals\tyxffmxendmono[] package\FgEndcap[]
-\Comp[]\tyxtstxbf[]with\tyxtstxendbf[] lists;
-\tyxtstxbf[]package\tyxtstxendbf[] radicals \tyxtstxbf[]is%
-\tyxtstxendbf[]
-   \tyxtstxbf[]type\tyxtstxendbf[] radical\Symuns[]kind %
-\tyxtstxbf[]is\tyxtstxendbf[] (hydrogen, carboniferous);
-   \tyxtstxbf[]type\tyxtstxendbf[] radical\Symuns[]node (kind : radical\Symuns[]kind);
-   \tyxtstxbf[]type\tyxtstxendbf[] radical           %
-\tyxtstxbf[]is\tyxtstxendbf[] \tyxtstxbf[]access\tyxtstxendbf[] radical\Symuns[]node;
-   \tyxtstxbf[]type\tyxtstxendbf[] array\Symuns[]of\Symuns[]radicals %
-\tyxtstxbf[]is\tyxtstxendbf[] \tyxtstxbf[]array\tyxtstxendbf[] (positive %
-\tyxtstxbf[]range\tyxtstxendbf[] \Symlt[]\Symgt[]) \tyxtstxbf[]of%
-\tyxtstxendbf[] radical;
-   \tyxtstxbf[]subtype\tyxtstxendbf[] two\Symuns[]radicals   %
-\tyxtstxbf[]is\tyxtstxendbf[] array\Symuns[]of\Symuns[]radicals (1 .. 2);
-   \tyxtstxbf[]subtype\tyxtstxendbf[] three\Symuns[]radicals %
-\tyxtstxbf[]is\tyxtstxendbf[] array\Symuns[]of\Symuns[]radicals (1 .. 3);
-   \tyxtstxbf[]subtype\tyxtstxendbf[] four\Symuns[]radicals  %
-\tyxtstxbf[]is\tyxtstxendbf[] array\Symuns[]of\Symuns[]radicals (1 .. 4);
-   \tyxtstxbf[]type\tyxtstxendbf[] radical\Symuns[]node (kind : radical\Symuns[]kind) %
-\tyxtstxbf[]is\tyxtstxendbf[] \tyxtstxbf[]record\tyxtstxendbf[]
-      \tyxtstxbf[]case\tyxtstxendbf[] kind \tyxtstxbf[]is%
-\tyxtstxendbf[]
-      \tyxtstxbf[]when\tyxtstxendbf[] hydrogen =\Symgt[]
-         \tyxtstxbf[]null\tyxtstxendbf[];
-      \tyxtstxbf[]when\tyxtstxendbf[] carboniferous =\Symgt[]
-         carbon\Symuns[]neighbors : three\Symuns[]radicals;
-      \tyxtstxbf[]end\tyxtstxendbf[] \tyxtstxbf[]case%
-\tyxtstxendbf[];
-   \tyxtstxbf[]end\tyxtstxendbf[] \tyxtstxbf[]record%
-\tyxtstxendbf[];
-   \tyxtstxbf[]package\tyxtstxendbf[] radical\Symuns[]lists %
-\tyxtstxbf[]is\tyxtstxendbf[] \tyxtstxbf[]new\tyxtstxendbf[] lists (radical);
-   \tyxtstxbf[]subtype\tyxtstxendbf[] radical\Symuns[]list  %
-\tyxtstxbf[]is\tyxtstxendbf[] radical\Symuns[]lists.list;
-   \tyxtstxbf[]type\tyxtstxendbf[] array\Symuns[]of\Symuns[]radical\Symuns[]lists %
-\tyxtstxbf[]is\tyxtstxendbf[]
-      \tyxtstxbf[]array\tyxtstxendbf[] (natural \tyxtstxbf[]range%
-\tyxtstxendbf[] \Symlt[]\Symgt[]) \tyxtstxbf[]of\tyxtstxendbf[] radical\Symuns[]list;
-   \tyxtstxbf[]function\tyxtstxendbf[] hydrogen\Symuns[]radical %
-\tyxtstxbf[]return\tyxtstxendbf[] radical;
-   \tyxtstxbf[]function\tyxtstxendbf[] radical\Symuns[]made\Symuns[]from (subradicals : three\Symuns[]radicals)
-      \tyxtstxbf[]return\tyxtstxendbf[] radical;
-\tyxtstxbf[]end\tyxtstxendbf[];\Endcomp[]
-\EndParbox[]
-\FgEndblock[]
- Radicals are trees whose nodes are of the type \tyxffmxmono[]radical\Symuns[]node%
-\tyxffmxendmono[], which is a record type with a discriminant indicating
-whether the node represents a hydrogen radical (which has no subnodes)
-or a carboniferous radical (which has three). The type %
-\tyxffmxmono[]radical\tyxffmxendmono[] is an access type whose designated
-type is \tyxffmxmono[]radical\Symuns[]node\tyxffmxendmono[]; thus
-a radical is represented by the pointer to its root node, which if
-not degenerate contains pointers to its subnodes, etc. An unconstrained
-array type providing for arrays of radicals is also declared, as are
-several constrained subtypes thereof with fixed numbers of components;
-one of these is used in the declaration of \tyxffmxmono[]radical\Symuns[]node%
-\tyxffmxendmono[]. Linked lists of radicals are obtained by instantiating
-with the type \tyxffmxmono[]radical\tyxffmxendmono[] a generic package
-called \tyxffmxmono[]lists\tyxffmxendmono[] which, because of its
-utility in diverse applications, we assume to be available as an application-independent
-library unit; the specification of \tyxffmxmono[]radicals%
-\tyxffmxendmono[] is compiled in its context. We do not show its definition
-here, and we merely remark that we assume it exports at least a type
-called \tyxffmxmono[]list\tyxffmxendmono[]; \tyxffmxmono[]head%
-\tyxffmxendmono[], \tyxffmxmono[]tail\tyxffmxendmono[], and %
-\tyxffmxmono[]is\Symuns[]empty\tyxffmxendmono[] functions; and an
-\tyxffmxmono[]append\tyxffmxendmono[] procedure. We furthermore assume
-that lists are initially empty. Another unconstrained array type providing
-for arrays of linked lists of radicals is declared, and finally two
-functions are declared\EmDash[]one for allocating, and returning a
-pointer to, an object of type \tyxffmxmono[]radical\Symuns[]node%
-\tyxffmxendmono[] representing a hydrogen radical, and one for allocating,
-and returning a pointer to, an object of type \tyxffmxmono[]radical\Symuns[]node%
-\tyxffmxendmono[] representing a carboniferous paraffin radical made
-from pointers to the objects of type \tyxffmxmono[]radical\Symuns[]node%
-\tyxffmxendmono[] that are its subnodes.\Endpara[]
-\Para[]The body of the \tyxffmxmono[]radicals\tyxffmxendmono[] package
-is shown in Figure \Xref[\def\XrefName{body-of-radicals}];
-\FgBlock[\def\FgBlockPlace{H}]
-\Parbox[]
-\FgCap[\def\FgCapId{body-of-radicals}]Body of the \tyxffmxmono[]radicals%
-\tyxffmxendmono[] package\FgEndcap[]
-\Comp[]\tyxtstxbf[]package\tyxtstxendbf[] \tyxtstxbf[]body%
-\tyxtstxendbf[] radicals \tyxtstxbf[]is\tyxtstxendbf[]
-   \tyxtstxbf[]function\tyxtstxendbf[] hydrogen\Symuns[]radical %
-\tyxtstxbf[]return\tyxtstxendbf[] radical \tyxtstxbf[]is%
-\tyxtstxendbf[]
-   \tyxtstxbf[]begin\tyxtstxendbf[]
-      \tyxtstxbf[]return\tyxtstxendbf[] \tyxtstxbf[]new%
-\tyxtstxendbf[] radical\Symuns[]node\rsquo[](kind =\Symgt[] hydrogen);
-   \tyxtstxbf[]end\tyxtstxendbf[];
-   \tyxtstxbf[]function\tyxtstxendbf[] radical\Symuns[]made\Symuns[]from (subradicals : three\Symuns[]radicals)
-      \tyxtstxbf[]return\tyxtstxendbf[] radical \tyxtstxbf[]is%
-\tyxtstxendbf[]
-   \tyxtstxbf[]begin\tyxtstxendbf[]
-      \tyxtstxbf[]return\tyxtstxendbf[] \tyxtstxbf[]new%
-\tyxtstxendbf[] radical\Symuns[]node\rsquo[](kind             =\Symgt[] carboniferous,
-                               carbon\Symuns[]neighbors =\Symgt[] subradicals);
-   \tyxtstxbf[]end\tyxtstxendbf[];
-\tyxtstxbf[]end\tyxtstxendbf[];\Endcomp[]
-\EndParbox[]
-\FgEndblock[]
- it contains the bodies of the radical-constructing functions declared
-in its specification. These are simple enough that they should need
-no explanation.\Endpara[]
-\Para[]The specification of the \tyxffmxmono[]molecules%
-\tyxffmxendmono[] package is shown in Figure \Xref[\def\XrefName{spec-of-molecules}].
-\FgBlock[\def\FgBlockPlace{H}]
-\Parbox[]
-\FgCap[\def\FgCapId{spec-of-molecules}]Specification of the %
-\tyxffmxmono[]molecules\tyxffmxendmono[] package\FgEndcap[]
-\Comp[]\tyxtstxbf[]with\tyxtstxendbf[] radicals, lists;
-\tyxtstxbf[]use\tyxtstxendbf[]  radicals;
-\tyxtstxbf[]package\tyxtstxendbf[] molecules \tyxtstxbf[]is%
-\tyxtstxendbf[]
-   \tyxtstxbf[]type\tyxtstxendbf[] molecule\Symuns[]kind %
-\tyxtstxbf[]is\tyxtstxendbf[] (bond\Symuns[]centered, carbon\Symuns[]centered);
-   \tyxtstxbf[]type\tyxtstxendbf[] molecule\Symuns[]node (kind : molecule\Symuns[]kind) %
-\tyxtstxbf[]is\tyxtstxendbf[] \tyxtstxbf[]record\tyxtstxendbf[]
-      \tyxtstxbf[]case\tyxtstxendbf[] kind \tyxtstxbf[]is%
-\tyxtstxendbf[]
-      \tyxtstxbf[]when\tyxtstxendbf[] bond\Symuns[]centered =\Symgt[]
-         bond\Symuns[]neighbors : two\Symuns[]radicals;
-      \tyxtstxbf[]when\tyxtstxendbf[] carbon\Symuns[]centered =\Symgt[]
-         carbon\Symuns[]neighbors : four\Symuns[]radicals;
-      \tyxtstxbf[]end\tyxtstxendbf[] \tyxtstxbf[]case%
-\tyxtstxendbf[];
-   \tyxtstxbf[]end\tyxtstxendbf[] \tyxtstxbf[]record%
-\tyxtstxendbf[];
-   \tyxtstxbf[]type\tyxtstxendbf[] molecule \tyxtstxbf[]is%
-\tyxtstxendbf[] \tyxtstxbf[]access\tyxtstxendbf[] molecule\Symuns[]node;
-   \tyxtstxbf[]package\tyxtstxendbf[] molecule\Symuns[]lists %
-\tyxtstxbf[]is\tyxtstxendbf[] \tyxtstxbf[]new\tyxtstxendbf[] lists (molecule);
-   \tyxtstxbf[]subtype\tyxtstxendbf[] molecule\Symuns[]list  %
-\tyxtstxbf[]is\tyxtstxendbf[] molecule\Symuns[]lists.list;
-   \tyxtstxbf[]type\tyxtstxendbf[] array\Symuns[]of\Symuns[]molecule\Symuns[]lists %
-\tyxtstxbf[]is\tyxtstxendbf[]
-      \tyxtstxbf[]array\tyxtstxendbf[] (positive \tyxtstxbf[]range%
-\tyxtstxendbf[] \Symlt[]\Symgt[]) \tyxtstxbf[]of\tyxtstxendbf[] molecule\Symuns[]list;
-   \tyxtstxbf[]function\tyxtstxendbf[] molecule\Symuns[]made\Symuns[]from (radicals : array\Symuns[]of\Symuns[]radicals)
-      \tyxtstxbf[]return\tyxtstxendbf[] molecule;
-\tyxtstxbf[]end\tyxtstxendbf[];\Endcomp[]
-\EndParbox[]
-\FgEndblock[]
-\TyPbrkNewp[]
- Molecules are trees whose root nodes are of the type %
-\tyxffmxmono[]molecule\Symuns[]node\tyxffmxendmono[], which is a record
-type with a discriminant indicating whether the node represents a
-BCP (which has two subnodes) or a CCP (which has four). The type %
-\tyxffmxmono[]molecule\tyxffmxendmono[] is an access type whose designated
-type is \tyxffmxmono[]molecule\Symuns[]node\tyxffmxendmono[]; thus
-a molecule is represented by the pointer to its root node, which contains
-pointers to its subnodes, etc. Note that the types %
-\tyxffmxmono[]molecule\Symuns[]node\tyxffmxendmono[] and %
-\tyxffmxmono[]molecule\tyxffmxendmono[], unlike the types %
-\tyxffmxmono[]radical\Symuns[]node\tyxffmxendmono[] and %
-\tyxffmxmono[]radical\tyxffmxendmono[], are not recursive types. That
-is, the subnodes of a molecule are not molecules but radicals. To
-achieve visibility to the types associated with radicals, we compile
-the specification of \tyxffmxmono[]molecules\tyxffmxendmono[] in the
-context of \tyxffmxmono[]radicals\tyxffmxendmono[] (that is, it \ldquo[]withs\rdquo[]
-\tyxffmxmono[]radicals\tyxffmxendmono[]). Linked lists of molecules
-are obtained by instantiating with the type \tyxffmxmono[]molecule%
-\tyxffmxendmono[] the previously discussed generic package %
-\tyxffmxmono[]lists\tyxffmxendmono[], which is therefore also named
-in the context clause of the specification of \tyxffmxmono[]molecules%
-\tyxffmxendmono[]. An unconstrained array type providing for arrays
-of linked lists of molecules is declared, and finally we declare a
-function for allocating, and returning a pointer to, an object of
-type \tyxffmxmono[]molecule\Symuns[]node\tyxffmxendmono[], made from
-pointers to the objects of type \tyxffmxmono[]radical\Symuns[]node%
-\tyxffmxendmono[] that are its subnodes.\Endpara[]
-\Para[]The body of the \tyxffmxmono[]molecules\tyxffmxendmono[] package
-is shown in Figure \Xref[\def\XrefName{body-of-molecules}];
-\FgBlock[\def\FgBlockPlace{H}]
-\Parbox[]
-\FgCap[\def\FgCapId{body-of-molecules}]Body of the %
-\tyxffmxmono[]molecules\tyxffmxendmono[] package\FgEndcap[]
-\Comp[]\tyxtstxbf[]package\tyxtstxendbf[] \tyxtstxbf[]body%
-\tyxtstxendbf[] molecules \tyxtstxbf[]is\tyxtstxendbf[]
-   \tyxtstxbf[]function\tyxtstxendbf[] molecule\Symuns[]made\Symuns[]from (radicals : array\Symuns[]of\Symuns[]radicals)
-      \tyxtstxbf[]return\tyxtstxendbf[] molecule \tyxtstxbf[]is%
-\tyxtstxendbf[]
-   \tyxtstxbf[]begin\tyxtstxendbf[]
-      \tyxtstxbf[]if\tyxtstxendbf[] radicals\rsquo[]length = 2 %
-\tyxtstxbf[]then\tyxtstxendbf[]
-         \tyxtstxbf[]return\tyxtstxendbf[] \tyxtstxbf[]new%
-\tyxtstxendbf[] molecule\Symuns[]node\rsquo[](kind =\Symgt[] bond\Symuns[]centered,
-                                   bond\Symuns[]neighbors =\Symgt[] radicals);
-      \tyxtstxbf[]else\tyxtstxendbf[] -- Must be 4.
-         \tyxtstxbf[]return\tyxtstxendbf[] \tyxtstxbf[]new%
-\tyxtstxendbf[] molecule\Symuns[]node\rsquo[](kind =\Symgt[] carbon\Symuns[]centered,
-                                   carbon\Symuns[]neighbors =\Symgt[] radicals);
-      \tyxtstxbf[]end\tyxtstxendbf[] \tyxtstxbf[]if%
-\tyxtstxendbf[];
-   \tyxtstxbf[]end\tyxtstxendbf[];
-\tyxtstxbf[]end\tyxtstxendbf[];\Endcomp[]
-\EndParbox[]
-\FgEndblock[]
- it contains the body of the molecule-constructing function declared
-in its specification. It is simple enough that it should need no explanation.%
-\Endpara[]
-\Para[]The reader should return to the body of \tyxffmxmono[]paraffins%
-\tyxffmxendmono[] (Figure \Xref[\def\XrefName{body-of-paraffins-serial}])
-for a moment. The function of the use clause in the context clause
-preceding the \tyxffmxmono[]paraffins\tyxffmxendmono[] function is
-to provide direct visibility to the names declared in both %
-\tyxffmxmono[]radicals\tyxffmxendmono[] and \tyxffmxmono[]molecules%
-\tyxffmxendmono[]. These names include \tyxffmxmono[]radical\Symuns[]lists%
-\tyxffmxendmono[] and \tyxffmxmono[]molecule\Symuns[]lists%
-\tyxffmxendmono[], the packages obtained in \tyxffmxmono[]radicals%
-\tyxffmxendmono[] and \tyxffmxmono[]molecules\tyxffmxendmono[] by
-the instantiation therein of \tyxffmxmono[]lists%
-\tyxffmxendmono[]. However, the visible names do not include those
-of the operations on lists (\tyxffmxmono[]head\tyxffmxendmono[], %
-\tyxffmxmono[]tail\tyxffmxendmono[], \tyxffmxmono[]append%
-\tyxffmxendmono[], \tyxffmxmono[]is\Symuns[]empty%
-\tyxffmxendmono[]), since those operations are not declared in %
-\tyxffmxmono[]radicals\tyxffmxendmono[] or \tyxffmxmono[]molecules%
-\tyxffmxendmono[]. It is the function of the second use clause, the
-one in the declarative part of the \tyxffmxmono[]paraffins%
-\tyxffmxendmono[] function, to provide direct visibility to them.
-Note that the same set of subprogram
-\TyPbrkNewp[]
- names is exported by both \tyxffmxmono[]radical\Symuns[]lists%
-\tyxffmxendmono[] and \tyxffmxmono[]molecule\Symuns[]lists%
-\tyxffmxendmono[]. How does the compiler know from which of these
-packages the name \tyxffmxmono[]append\tyxffmxendmono[], appearing
-later in \tyxffmxmono[]paraffins\tyxffmxendmono[], comes? The answer
-is that the overloaded names of the two \tyxffmxmono[]append%
-\tyxffmxendmono[] procedures are disambiguated by overload resolution,
-based on the types of the actual parameters in a call; the same is
-true of calls to \tyxffmxmono[]head\tyxffmxendmono[], %
-\tyxffmxmono[]tail\tyxffmxendmono[], \tyxffmxmono[]is\Symuns[]empty%
-\tyxffmxendmono[], and other calls to \tyxffmxmono[]append%
-\tyxffmxendmono[] in other parts of the solution. No such overload
-resolution occurs, however, for the type name \tyxffmxmono[]list%
-\tyxffmxendmono[] exported by both \tyxffmxmono[]radical\Symuns[]lists%
-\tyxffmxendmono[] and \tyxffmxmono[]molecule\Symuns[]lists%
-\tyxffmxendmono[]; in fact, the two occurrences of the identical type
-name cancel each other out, and neither is directly visible by the
-simple name \tyxffmxmono[]list\tyxffmxendmono[] in %
-\tyxffmxmono[]paraffins\tyxffmxendmono[] or in subunits thereof. That
-is why we declared the subtype \tyxffmxmono[]radical\Symuns[]list%
-\tyxffmxendmono[] in the specification of \tyxffmxmono[]radicals%
-\tyxffmxendmono[] as being synonymous with the type %
-\tyxffmxmono[]list\tyxffmxendmono[] exported by \tyxffmxmono[]radical\Symuns[]lists%
-\tyxffmxendmono[], and the subtype \tyxffmxmono[]molecule\Symuns[]list%
-\tyxffmxendmono[] in the specification of \tyxffmxmono[]molecules%
-\tyxffmxendmono[] as being synonymous with the type %
-\tyxffmxmono[]list\tyxffmxendmono[] exported by \tyxffmxmono[]molecule\Symuns[]lists%
-\tyxffmxendmono[]. So, in \tyxffmxmono[]paraffins%
-\tyxffmxendmono[] and its subunits, we use the name %
-\tyxffmxmono[]radical\Symuns[]list\tyxffmxendmono[] or %
-\tyxffmxmono[]molecule\Symuns[]list\tyxffmxendmono[] as appropriate,
-instead of the ambiguous (and not even directly visible) name %
-\tyxffmxmono[]list\tyxffmxendmono[].\NtFoot[]\NtNtpar[]Actually, the
-only use of either name in one of these places is in the proper body
-of the generic procedure \tyxffmxmono[]enum\Symuns[]rad\Symuns[]tuples%
-\tyxffmxendmono[], which is one of the subunits of %
-\tyxffmxmono[]paraffins\tyxffmxendmono[]; see Figure \Xref[\def\XrefName{body-of-enum-rad-tuples}].%
-\NtEndntpar[]\NtEndfoot[]\Endpara[]
-\Para[]We turn now to the real work of constructing paraffin radicals,
-BCPs, and CCPs.\Endpara[]
-\Para[]Radicals of size \InlEqn[]\LmthEqn[]i
-\LmthEndeqn[]\EndInlEqn[], for \InlEqn[]\LmthEqn[]i>0
-\LmthEndeqn[]%
-\EndInlEqn[], are generated by first enumerating all ordered, nondecreasing,
-ternary partitions of \InlEqn[]\LmthEqn[]i-1
-\LmthEndeqn[]\EndInlEqn[]. The partitions are enumerated
-in a natural order. (For example, the ordered, nondecreasing, ternary
-partitions of 7 are enumerated in the order (0,0,7), (0,1,6), (0,2,5),
-(0,3,4), (1,1,5), (1,2,4), (1,3,3), (2,2,3).) Each such partition
-gives the sizes of the three subradicals that need to be attached
-(in order) to a carbon atom to obtain a radical of size %
-\InlEqn[]\LmthEqn[]i
-\LmthEndeqn[]\EndInlEqn[]; since the maximum size of any of these subradicals
-is \InlEqn[]\LmthEqn[]i-1
-\LmthEndeqn[]\EndInlEqn[], they are guaranteed to have been created
-earlier (remember that the radicals are created in order of size).
-As each such partition is enumerated, we subordinately enumerate all
-lexicographically ordered triples of radicals having the indicated
-sizes. Each such triple gives the actual subradicals that need to
-be attached (in order) to a carbon atom to obtain a radical of size
-\InlEqn[]\LmthEqn[]i
-\LmthEndeqn[]\EndInlEqn[]. This overall process generates the radicals
-of size \InlEqn[]\LmthEqn[]i
-\LmthEndeqn[]\EndInlEqn[] in lexicographic order.\Endpara[]
-\Para[]CCPs of size \InlEqn[]\LmthEqn[]i
-\LmthEndeqn[]\EndInlEqn[] are generated by using the
-same process, with different parameters. First we enumerate all ordered,
-nondecreasing, \txtxemph[]quaternary\txtxendemph[] partitions of %
-\InlEqn[]\LmthEqn[]i-1
-\LmthEndeqn[]\EndInlEqn[] having elements of maximum size \InlEqn[]\LmthEqn[]
-\left\lfloor {{{i-1} \over {2}}}
-\right\rfloor 
-\LmthEndeqn[]%
-\EndInlEqn[]. Each such partition gives the sizes of the four radicals
-that need to be attached (in order) to a carbon atom to obtain a CCP
-of size \InlEqn[]\LmthEqn[]i
-\LmthEndeqn[]\EndInlEqn[]; the radicals are guaranteed to have
-been created earlier (remember that the radicals are created before
-the molecules). As each such partition is enumerated, we subordinately
-enumerate all lexicographically ordered quads of radicals having the
-indicated sizes. Each such quad gives the actual radicals that need
-to be attached (in order) to a carbon atom to obtain a CCP of size
-\InlEqn[]\LmthEqn[]i
-\LmthEndeqn[]\EndInlEqn[].\Endpara[]
-\Para[]In theory, we do not need to enumerate partitions to obtain
-the sizes of the constituent radicals of BCPs of size \InlEqn[]\LmthEqn[]i
-\LmthEndeqn[]%
-\EndInlEqn[], since the only partition we need is \InlEqn[]\LmthEqn[]
-\left( {{{i} \over {2}},{{i} \over {2}}}
-\right) 
-\LmthEndeqn[]%
-\EndInlEqn[], and it can be obtained simply by constructing its sole
-element. However, we can reuse the software components used for generating
-radicals and CCPs by supplying them with parameters that will enumerate
-all ordered, nondecreasing, \txtxemph[]binary\txtxendemph[] partitions
-of \InlEqn[]\LmthEqn[]i
-\LmthEndeqn[]\EndInlEqn[] having elements of both minimum and maximum
-size \InlEqn[]\LmthEqn[]{{i} \over {2}}
-\LmthEndeqn[]\EndInlEqn[]; of course, there will be only one. This
-partition gives the sizes of the two radicals that need to be attached
-(in order) to a carbon-carbon bond to obtain a BCP of size %
-\InlEqn[]\LmthEqn[]i
-\LmthEndeqn[]\EndInlEqn[]. Subordinately, we enumerate all lexicographically
-ordered pairs of radicals having the indicated sizes. Each such pair
-gives the actual radicals that need to be attached (in order) to a
-carbon-carbon bond to obtain a BCP of size \InlEqn[]\LmthEqn[]i
-\LmthEndeqn[]\EndInlEqn[].%
-\Endpara[]
-\Para[]From the preceding discussion, it should be clear that a central
-component of our solution is a procedure that enumerates all the ordered,
-nondecreasing partitions of a given positive integer into a given
-number of elements each bounded by a given minimum and maximum. This
-suggests a procedure with four formal parameters. Actually, a fifth
-parameter is needed: the name of the procedure encapsulating the operation
-to be applied to each partition as it is enumerated (that operation
-is the one that enumerates the tuples of radicals of the sizes given
-by the partition). Since parameterization by a procedure can currently
-be accomplished in Ada only with the use of generic units, we make
-our partition-enumerating procedure into a generic procedure. It is
-called \tyxffmxmono[]enum\Symuns[]partitions\tyxffmxendmono[], and
-its specification is shown in Figure \Xref[\def\XrefName{spec-of-enum-partitions}].
-\FgBlock[\def\FgBlockPlace{H}]
-\Parbox[]
-\FgCap[\def\FgCapId{spec-of-enum-partitions}]Specification of the
-\tyxffmxmono[]enum\Symuns[]partitions\tyxffmxendmono[] generic procedure%
-\FgEndcap[]
-\Comp[]\tyxtstxbf[]generic\tyxtstxendbf[]
-   \tyxtstxbf[]type\tyxtstxendbf[] array\Symuns[]type %
-\tyxtstxbf[]is\tyxtstxendbf[] \tyxtstxbf[]array\tyxtstxendbf[] (positive %
-\tyxtstxbf[]range\tyxtstxendbf[] \Symlt[]\Symgt[]) \tyxtstxbf[]of%
-\tyxtstxendbf[] natural;
-   \tyxtstxbf[]with\tyxtstxendbf[] \tyxtstxbf[]procedure%
-\tyxtstxendbf[] apply\Symuns[]to\Symuns[]each (p : \tyxtstxbf[]in%
-\tyxtstxendbf[] array\Symuns[]type);
-\tyxtstxbf[]procedure\tyxtstxendbf[] enum\Symuns[]partitions (sum\Symuns[]of\Symuns[]elements : %
-\tyxtstxbf[]in\tyxtstxendbf[] natural;
-                           nbr\Symuns[]of\Symuns[]elements : %
-\tyxtstxbf[]in\tyxtstxendbf[] positive;
-                           min\Symuns[]element     : %
-\tyxtstxbf[]in\tyxtstxendbf[] natural;
-                           max\Symuns[]element     : %
-\tyxtstxbf[]in\tyxtstxendbf[] natural);\Endcomp[]
-\EndParbox[]
-\FgEndblock[]
- Since the declaration of the generic formal subprogram parameter,
-named \tyxffmxmono[]apply\Symuns[]to\Symuns[]each%
-\tyxffmxendmono[], must mention a type\EmDash[]that of the array used
-to pass an enumerated partition to the actual subprogram associated
-with \tyxffmxmono[]apply\Symuns[]to\Symuns[]each%
-\tyxffmxendmono[]\EmDash[]we make that type another generic formal
-parameter, named \tyxffmxmono[]array\Symuns[]type%
-\tyxffmxendmono[]. In so doing, we import into \tyxffmxmono[]enum\Symuns[]partitions%
-\tyxffmxendmono[] everything it needs to be instantiated for an application;
-it gets nothing else from a global scope or a context clause and can
-therefore be an application-independent library unit. So, the generic
-procedure \tyxffmxmono[]enum\Symuns[]partitions\tyxffmxendmono[] has
-two generic formal parameters, and the ordinary procedure that is
-obtained by instantiating it has four ordinary formal parameters.
-The body of \tyxffmxmono[]enum\Symuns[]partitions%
-\tyxffmxendmono[] will be shown later.\Endpara[]
-\Para[]We can anticipate three instantiations of \tyxffmxmono[]enum\Symuns[]partitions%
-\tyxffmxendmono[]\EmDash[]for generating radicals, BPCs, and CCPs.
-What procedures will be associated with \tyxffmxmono[]apply\Symuns[]to\Symuns[]each%
-\tyxffmxendmono[] in those three instantiations, and what types with
-\tyxffmxmono[]array\Symuns[]type\tyxffmxendmono[]? The second part
-of the question will be answered later, when we actually look at the
-instantiations. The three procedures we need for the generic actual
-subprogram parameters all have much in common: they take an array
-specifying a nondecreasing sequence of radical sizes and must enumerate
-all tuples of lexicographically ordered radicals of the corresponding
-sizes. This suggests a procedure with one formal parameter. However,
-another parameter is needed: the name of a procedure encapsulating
-the operation to be applied to each tuple as it is enumerated (that
-operation is the one that actually constructs a radical, BCP, or CCP
-from the tuple of radicals and appends it to the appropriate list).
-Again, we require the use of generic units. Thus, the three tuple-enumerating
-procedures will be obtained by instantiating a second generic procedure,
-which we call \tyxffmxmono[]enum\Symuns[]rad\Symuns[]tuples%
-\tyxffmxendmono[]. Unlike \tyxffmxmono[]enum\Symuns[]partitions%
-\tyxffmxendmono[], \tyxffmxmono[]enum\Symuns[]rad\Symuns[]tuples%
-\tyxffmxendmono[] is very much application specific; it needs to access
-the list of radicals of a given size \InlEqn[]\LmthEqn[]i
-\LmthEndeqn[]\EndInlEqn[]\EmDash[]that
-is, \tyxffmxmono[]r\Symuns[]array(i)\tyxffmxendmono[]. The simplest
-way to give it that visibility is to nest it within %
-\tyxffmxmono[]paraffins\tyxffmxendmono[] (see Figure \Xref[\def\XrefName{body-of-paraffins-serial}]).
-Its body, a subunit of \tyxffmxmono[]paraffins\tyxffmxendmono[], is
-shown later.\Endpara[]
-\Para[]We can now turn to the three procedures that %
-\tyxffmxmono[]paraffins\tyxffmxendmono[] calls: \tyxffmxmono[]generate\Symuns[]rad%
-\tyxdishyph[]icals\Symuns[]of\Symuns[]size\tyxffmxendmono[], %
-\tyxffmxmono[]generate\Symuns[]ccps\Symuns[]of\Symuns[]size%
-\tyxffmxendmono[], and \tyxffmxmono[]generate\Symuns[]bcps\Symuns[]of\Symuns[]size%
-\tyxffmxendmono[]. Their specifications were in \tyxffmxmono[]paraffins%
-\tyxffmxendmono[], and their bodies were occupied there by body stubs.
-The proper body of \tyxffmxmono[]generate\Symuns[]radicals\Symuns[]of\Symuns[]size%
-\tyxffmxendmono[] is shown in Figure
-\FgBlock[\def\FgBlockPlace{H}]
-\Parbox[]
-\FgCap[\def\FgCapId{body-of-generate-radicals-of-size}]Proper body
-of the \tyxffmxmono[]generate\Symuns[]radicals\Symuns[]of\Symuns[]size%
-\tyxffmxendmono[] procedure\FgEndcap[]
-\Comp[]\tyxtstxbf[]with\tyxtstxendbf[] enum\Symuns[]partitions;
-\tyxtstxbf[]separate\tyxtstxendbf[] (paraffins)
-\tyxtstxbf[]procedure\tyxtstxendbf[] generate\Symuns[]radicals\Symuns[]of\Symuns[]size (i : %
-\tyxtstxbf[]in\tyxtstxendbf[] positive) \tyxtstxbf[]is%
-\tyxtstxendbf[]
-   \tyxtstxbf[]procedure\tyxtstxendbf[] make\Symuns[]and\Symuns[]append\Symuns[]rad (triple : %
-\tyxtstxbf[]in\tyxtstxendbf[] three\Symuns[]radicals) %
-\tyxtstxbf[]is\tyxtstxendbf[] 
-   \tyxtstxbf[]begin\tyxtstxendbf[]
-      append (radical\Symuns[]made\Symuns[]from(triple), to =\Symgt[] r\Symuns[]array(i));
-   \tyxtstxbf[]end\tyxtstxendbf[];
-   \tyxtstxbf[]procedure\tyxtstxendbf[] enum\Symuns[]subrads\Symuns[]for\Symuns[]rads %
-\tyxtstxbf[]is\tyxtstxendbf[]
-      \tyxtstxbf[]new\tyxtstxendbf[] enum\Symuns[]rad\Symuns[]tuples (apply\Symuns[]to\Symuns[]each =\Symgt[] make\Symuns[]and\Symuns[]append\Symuns[]rad);
-   \tyxtstxbf[]procedure\tyxtstxendbf[] enum\Symuns[]partitions\Symuns[]for\Symuns[]rads %
-\tyxtstxbf[]is\tyxtstxendbf[]
-      \tyxtstxbf[]new\tyxtstxendbf[] enum\Symuns[]partitions (array\Symuns[]type    =\Symgt[] array\Symuns[]of\Symuns[]naturals,
-                           apply\Symuns[]to\Symuns[]each =\Symgt[] enum\Symuns[]subrads\Symuns[]for\Symuns[]rads);
-\tyxtstxbf[]begin\tyxtstxendbf[]
-   enum\Symuns[]partitions\Symuns[]for\Symuns[]rads (sum\Symuns[]of\Symuns[]elements =\Symgt[] i-1,
-                             nbr\Symuns[]of\Symuns[]elements =\Symgt[] 3,
-                             min\Symuns[]element     =\Symgt[] 0,
-                             max\Symuns[]element     =\Symgt[] i-1);
-\tyxtstxbf[]end\tyxtstxendbf[];\Endcomp[]
-\EndParbox[]
-\FgEndblock[]
- \Xref[\def\XrefName{body-of-generate-radicals-of-size}]. We see there
-\LstList[]
-\LstItem[]the self-specifying body of a local procedure, %
-\tyxffmxmono[]make\Symuns[]and\Symuns[]append\Symuns[]rad%
-\tyxffmxendmono[], that takes an array of three radicals, makes a
-new radical with them as subradicals, and appends the new radical
-to \tyxffmxmono[]r\Symuns[]array(i)\tyxffmxendmono[], where %
-\tyxffmxmono[]i\tyxffmxendmono[] is the formal parameter of %
-\tyxffmxmono[]generate\Symuns[]radicals\Symuns[]of\Symuns[]size%
-\tyxffmxendmono[];\LstEnditem[]
-\LstItem[]an instantiation of the generic procedure %
-\tyxffmxmono[]enum\Symuns[]rad\Symuns[]tuples\tyxffmxendmono[] (visible
-because it is declared in the parent unit, \tyxffmxmono[]paraffins%
-\tyxffmxendmono[]) with \tyxffmxmono[]make\Symuns[]and\Symuns[]append\Symuns[]rad%
-\tyxffmxendmono[] as generic actual parameter, to yield the ordinary
-procedure \tyxffmxmono[]enum\Symuns[]sub\tyxdishyph[]rads\Symuns[]for\Symuns[]rads%
-\tyxffmxendmono[];\LstEnditem[]
-\LstItem[]an instantiation of the generic procedure %
-\tyxffmxmono[]enum\Symuns[]partitions\tyxffmxendmono[] (visible because
-of the context clause) with \tyxffmxmono[]enum\Symuns[]subrads\Symuns[]for\Symuns[]rads%
-\tyxffmxendmono[] and \tyxffmxmono[]array\Symuns[]of\Symuns[]naturals%
-\tyxffmxendmono[]\NtFoot[]\NtNtpar[]This unconstrained array type
-was declared in the parent unit, \tyxffmxmono[]paraffins%
-\tyxffmxendmono[]. We explained in the preceding paragraph why %
-\tyxffmxmono[]enum\Symuns[]partitions\tyxffmxendmono[] was invested
-with the generic formal type \tyxffmxmono[]array\Symuns[]type%
-\tyxffmxendmono[], with which \tyxffmxmono[]array\Symuns[]of\Symuns[]naturals%
-\tyxffmxendmono[] is here associated. The other generic procedure,
-\tyxffmxmono[]enum\Symuns[]rad\Symuns[]tuples\tyxffmxendmono[], needs
-\tyxffmxmono[]array\Symuns[]of\Symuns[]naturals\tyxffmxendmono[] as
-well; however, since that generic procedure is quite problem specific
-anyway, and for that reason is nested within \tyxffmxmono[]paraffins%
-\tyxffmxendmono[], it obtains visibility of \tyxffmxmono[]array\Symuns[]of\Symuns[]naturals%
-\tyxffmxendmono[] by virtue of that nesting and does not need to import
-\tyxffmxmono[]array\Symuns[]of\Symuns[]naturals\tyxffmxendmono[] by
-generic parameter association.\NtEndntpar[]\NtEndfoot[] as generic
-actual parameters, to yield the ordinary procedure %
-\tyxffmxmono[]enum\Symuns[]partitions\Symuns[]for\Symuns[]rads%
-\tyxffmxendmono[]; and\LstEnditem[]
-\LstItem[]the call of \tyxffmxmono[]enum\Symuns[]partitions\Symuns[]for\Symuns[]rads%
-\tyxffmxendmono[] with appropriate expressions involving %
-\tyxffmxmono[]i\tyxffmxendmono[] as actual parameters.%
-\LstEnditem[]
-\LstEndlist[]
-Note that there is only one executable statement in %
-\tyxffmxmono[]generate\Symuns[]radicals\Symuns[]of\Symuns[]size%
-\tyxffmxendmono[].\Endpara[]
-\Para[]The proper body of \tyxffmxmono[]generate\Symuns[]ccps\Symuns[]of\Symuns[]size%
-\tyxffmxendmono[] is shown in Figure \Xref[\def\XrefName{body-of-generate-ccps-of-size}].
-\FgBlock[\def\FgBlockPlace{H}]
-\Parbox[]
-\FgCap[\def\FgCapId{body-of-generate-ccps-of-size}]Proper body of
-the \tyxffmxmono[]generate\Symuns[]ccps\Symuns[]of\Symuns[]size%
-\tyxffmxendmono[] procedure\FgEndcap[]
-\Comp[]\tyxtstxbf[]with\tyxtstxendbf[] enum\Symuns[]partitions;
-\tyxtstxbf[]separate\tyxtstxendbf[] (paraffins)
-\tyxtstxbf[]procedure\tyxtstxendbf[] generate\Symuns[]ccps\Symuns[]of\Symuns[]size (i : %
-\tyxtstxbf[]in\tyxtstxendbf[] positive) \tyxtstxbf[]is%
-\tyxtstxendbf[]
-   \tyxtstxbf[]procedure\tyxtstxendbf[] make\Symuns[]and\Symuns[]append\Symuns[]ccp (quad : %
-\tyxtstxbf[]in\tyxtstxendbf[] four\Symuns[]radicals) %
-\tyxtstxbf[]is\tyxtstxendbf[]
-   \tyxtstxbf[]begin\tyxtstxendbf[]
-      append (molecule\Symuns[]made\Symuns[]from(quad), to =\Symgt[] m\Symuns[]array(i));
-   \tyxtstxbf[]end\tyxtstxendbf[];
-   \tyxtstxbf[]procedure\tyxtstxendbf[] enum\Symuns[]rads\Symuns[]for\Symuns[]ccps %
-\tyxtstxbf[]is\tyxtstxendbf[]
-      \tyxtstxbf[]new\tyxtstxendbf[] enum\Symuns[]rad\Symuns[]tuples (apply\Symuns[]to\Symuns[]each =\Symgt[] make\Symuns[]and\Symuns[]append\Symuns[]ccp);
-   \tyxtstxbf[]procedure\tyxtstxendbf[] enum\Symuns[]partitions\Symuns[]for\Symuns[]ccps %
-\tyxtstxbf[]is\tyxtstxendbf[]
-      \tyxtstxbf[]new\tyxtstxendbf[] enum\Symuns[]partitions (array\Symuns[]type    =\Symgt[] array\Symuns[]of\Symuns[]naturals,
-                           apply\Symuns[]to\Symuns[]each =\Symgt[] enum\Symuns[]rads\Symuns[]for\Symuns[]ccps);
-\tyxtstxbf[]begin\tyxtstxendbf[]
-   enum\Symuns[]partitions\Symuns[]for\Symuns[]ccps (sum\Symuns[]of\Symuns[]elements =\Symgt[] i-1,
-                             nbr\Symuns[]of\Symuns[]elements =\Symgt[] 4,
-                             min\Symuns[]element     =\Symgt[] 0,
-                             max\Symuns[]element     =\Symgt[] (i-1)/2);
-\tyxtstxbf[]end\tyxtstxendbf[];\Endcomp[]
-\EndParbox[]
-\FgEndblock[]
- Its contents are analogous to those of \tyxffmxmono[]generate\Symuns[]radicals\Symuns[]of\Symuns[]size%
-\tyxffmxendmono[], differing only in the procedure %
-\tyxffmxmono[]make\Symuns[]and\Symuns[]append\Symuns[]ccp%
-\tyxffmxendmono[] at the head of the chain of instantiations and in
-the expressions involving \tyxffmxmono[]i\tyxffmxendmono[] in the
-call of the procedure at the tail of the chain of instantiations.%
-\Endpara[]
-\Para[]The analogous proper body of \tyxffmxmono[]generate\Symuns[]bcps\Symuns[]of\Symuns[]size%
-\tyxffmxendmono[] is shown in Figure \Xref[\def\XrefName{body-of-generate-bcps-of-size}].
-\FgBlock[\def\FgBlockPlace{H}]
-\Parbox[]
-\FgCap[\def\FgCapId{body-of-generate-bcps-of-size}]Proper body of
-the \tyxffmxmono[]generate\Symuns[]bcps\Symuns[]of\Symuns[]size%
-\tyxffmxendmono[] procedure\FgEndcap[]
-\Comp[]\tyxtstxbf[]with\tyxtstxendbf[] enum\Symuns[]partitions;
-\tyxtstxbf[]separate\tyxtstxendbf[] (paraffins)
-\tyxtstxbf[]procedure\tyxtstxendbf[] generate\Symuns[]bcps\Symuns[]of\Symuns[]size (i : %
-\tyxtstxbf[]in\tyxtstxendbf[] positive) \tyxtstxbf[]is%
-\tyxtstxendbf[]
-   \tyxtstxbf[]procedure\tyxtstxendbf[] make\Symuns[]and\Symuns[]append\Symuns[]bcp (pair : %
-\tyxtstxbf[]in\tyxtstxendbf[] two\Symuns[]radicals) \tyxtstxbf[]is%
-\tyxtstxendbf[] 
-   \tyxtstxbf[]begin\tyxtstxendbf[]
-      append (molecule\Symuns[]made\Symuns[]from(pair), to =\Symgt[] m\Symuns[]array(i));
-   \tyxtstxbf[]end\tyxtstxendbf[];
-   \tyxtstxbf[]procedure\tyxtstxendbf[] enum\Symuns[]rads\Symuns[]for\Symuns[]bcps %
-\tyxtstxbf[]is\tyxtstxendbf[]
-      \tyxtstxbf[]new\tyxtstxendbf[] enum\Symuns[]rad\Symuns[]tuples (apply\Symuns[]to\Symuns[]each =\Symgt[] make\Symuns[]and\Symuns[]append\Symuns[]bcp);
-   \tyxtstxbf[]procedure\tyxtstxendbf[] enum\Symuns[]partitions\Symuns[]for\Symuns[]bcps %
-\tyxtstxbf[]is\tyxtstxendbf[]
-      \tyxtstxbf[]new\tyxtstxendbf[] enum\Symuns[]partitions (array\Symuns[]type    =\Symgt[] array\Symuns[]of\Symuns[]naturals,
-                           apply\Symuns[]to\Symuns[]each =\Symgt[] enum\Symuns[]rads\Symuns[]for\Symuns[]bcps);
-\tyxtstxbf[]begin\tyxtstxendbf[]
-   enum\Symuns[]partitions\Symuns[]for\Symuns[]bcps (sum\Symuns[]of\Symuns[]elements =\Symgt[] i,
-                             nbr\Symuns[]of\Symuns[]elements =\Symgt[] 2,
-                             min\Symuns[]element     =\Symgt[] i/2,
-                             max\Symuns[]element     =\Symgt[] i/2);
-\tyxtstxbf[]end\tyxtstxendbf[];\Endcomp[]
-\EndParbox[]
-\FgEndblock[]
- Incidentally, the three procedures just discussed are so similar
-in structure that they could all be obtained by generic instantiation,
-with appropriate generic actual parameters, of one generic procedure.
-Little would be gained, however, so we do not pursue that here.%
-\Endpara[]
-\Para[]The total number of executable statements we have shown is
-still surprisingly small. The bulk of the executable statements in
-our solution is to be found in the bodies of the generic procedures
-\tyxffmxmono[]enum\Symuns[]partitions\tyxffmxendmono[] and %
-\tyxffmxmono[]enum\Symuns[]rad\Symuns[]tuples\tyxffmxendmono[], which
-are all the pieces of our solution that remain to be presented. The
-body of \tyxffmxmono[]enum\Symuns[]partitions\tyxffmxendmono[], which
-(as will be recalled) was designed as an application-independent library
-unit, is shown in Figure \Xref[\def\XrefName{body-of-enum-partitions}].
-\FgBlock[]
-\Parbox[]
-\FgCap[\def\FgCapId{body-of-enum-partitions}]Body of the %
-\tyxffmxmono[]enum\Symuns[]partitions\tyxffmxendmono[] generic procedure%
-\FgEndcap[]
-\Comp[]\tyxtstxbf[]with\tyxtstxendbf[] min\Symuns[]and\Symuns[]max;
-\tyxtstxbf[]procedure\tyxtstxendbf[] enum\Symuns[]partitions (sum\Symuns[]of\Symuns[]elements : %
-\tyxtstxbf[]in\tyxtstxendbf[] natural;
-                           nbr\Symuns[]of\Symuns[]elements : %
-\tyxtstxbf[]in\tyxtstxendbf[] positive;
-                           min\Symuns[]element     : %
-\tyxtstxbf[]in\tyxtstxendbf[] natural;
-                           max\Symuns[]element     : %
-\tyxtstxbf[]in\tyxtstxendbf[] natural) \tyxtstxbf[]is%
-\tyxtstxendbf[]
-   \tyxtstxbf[]package\tyxtstxendbf[] integer\Symuns[]min\Symuns[]and\Symuns[]max %
-\tyxtstxbf[]is\tyxtstxendbf[] \tyxtstxbf[]new\tyxtstxendbf[] min\Symuns[]and\Symuns[]max (integer);
-   \tyxtstxbf[]use\tyxtstxendbf[]     integer\Symuns[]min\Symuns[]and\Symuns[]max;
-   p : array\Symuns[]type (1 .. nbr\Symuns[]of\Symuns[]elements);
-   \tyxtstxbf[]procedure\tyxtstxendbf[] recursively\Symuns[]partition (level        : %
-\tyxtstxbf[]in\tyxtstxendbf[] positive;
-                                    remainder    : \tyxtstxbf[]in%
-\tyxtstxendbf[] natural;
-                                    prev\Symuns[]element : %
-\tyxtstxbf[]in\tyxtstxendbf[] natural) \tyxtstxbf[]is%
-\tyxtstxendbf[]
-      remaining\Symuns[]levels : \tyxtstxbf[]constant%
-\tyxtstxendbf[] natural := nbr\Symuns[]of\Symuns[]elements - level;
-   \tyxtstxbf[]begin\tyxtstxendbf[]
-      \tyxtstxbf[]if\tyxtstxendbf[] remaining\Symuns[]levels \Symgt[] 0 %
-\tyxtstxbf[]then\tyxtstxendbf[]
-         \tyxtstxbf[]for\tyxtstxendbf[] element \tyxtstxbf[]in%
-\tyxtstxendbf[] max(remainder - max\Symuns[]element*remaining\Symuns[]levels,
-                            prev\Symuns[]element) ..
-                        min(remainder - min\Symuns[]element*remaining\Symuns[]levels,
-                            remainder / (remaining\Symuns[]levels + 1)) %
-\tyxtstxbf[]loop\tyxtstxendbf[]
-            p(level) := element;
-            recursively\Symuns[]partition (level + 1,
-                                   remainder - element,
-                                   element);
-         \tyxtstxbf[]end\tyxtstxendbf[] \tyxtstxbf[]loop%
-\tyxtstxendbf[];
-      \tyxtstxbf[]else\tyxtstxendbf[]
-         p(level) := remainder;
-         apply\Symuns[]to\Symuns[]each (p);
-      \tyxtstxbf[]end\tyxtstxendbf[] \tyxtstxbf[]if%
-\tyxtstxendbf[];
-   \tyxtstxbf[]end\tyxtstxendbf[];
-\tyxtstxbf[]begin\tyxtstxendbf[]
-   recursively\Symuns[]partition (1, sum\Symuns[]of\Symuns[]elements, min\Symuns[]element);
-\tyxtstxbf[]end\tyxtstxendbf[];\Endcomp[]
-\EndParbox[]
-\FgEndblock[]
- The code in \tyxffmxmono[]enum\Symuns[]partitions%
-\tyxffmxendmono[] is tricky, but not profound. An inner procedure,
-\tyxffmxmono[]recursively\Symuns[]partition\tyxffmxendmono[], is called
-to assign the first element of the partition; it calls itself recursively
-to assign successive elements, until the last element is reached.
-At each level of recursion, it computes\NtFoot[]\NtNtpar[]This computation
-requires \tyxffmxmono[]min\tyxffmxendmono[] and \tyxffmxmono[]max%
-\tyxffmxendmono[] functions, which are obtained by generic instantiation,
-with the predefined type \tyxffmxmono[]integer\tyxffmxendmono[], of
-the same application-independent generic library package, %
-\tyxffmxmono[]min\Symuns[]and\Symuns[]max\tyxffmxendmono[], used in
-the solution of Hamming\rsquo[]s problem. The type %
-\tyxffmxmono[]integer\tyxffmxendmono[] is used as the generic actual
-parameter, rather than a subtype thereof, like \tyxffmxmono[]positive%
-\tyxffmxendmono[] or \tyxffmxmono[]natural\tyxffmxendmono[], because
-the argument expressions in the present invocations of %
-\tyxffmxmono[]min\tyxffmxendmono[] and \tyxffmxmono[]max%
-\tyxffmxendmono[] can yield negative values.\NtEndntpar[]%
-\NtEndfoot[] the range\EmDash[]possibly empty\EmDash[]of element values
-acceptable at that level, and it loops\NtFoot[]\NtNtpar[]The loop
-at each level of recursion contrasts with the statically nested loops
-and lack of recursion found in some other solutions; it has the advantage
-that it simulates an arbitrary level of nesting. Of course, this strategy
-was motivated by the desire to write a single generic procedure that
-could serve for the binary, ternary, and quaternary partitions needed
-for the problem solution.\NtEndntpar[]\NtEndfoot[] through those values
-(ascending to the next higher level for each in turn). At the highest
-level, when a partition has been enumerated, it applies the operation
-passed parametrically to the partition.\Endpara[]
-\Para[]The proper body of the remaining generic procedure, %
-\tyxffmxmono[]enum\Symuns[]rad\Symuns[]tuples\tyxffmxendmono[] (a
-subunit of \tyxffmxmono[]paraffins\tyxffmxendmono[]), is shown in
-Figure \Xref[\def\XrefName{body-of-enum-rad-tuples}].
-\FgBlock[]
-\Parbox[]
-\FgCap[\def\FgCapId{body-of-enum-rad-tuples}]Proper body of the %
-\tyxffmxmono[]enum\Symuns[]rad\Symuns[]tuples\tyxffmxendmono[] generic
-procedure\FgEndcap[]
-\Comp[]\tyxtstxbf[]separate\tyxtstxendbf[] (paraffins)
-\tyxtstxbf[]procedure\tyxtstxendbf[] enum\Symuns[]rad\Symuns[]tuples (p : %
-\tyxtstxbf[]in\tyxtstxendbf[] array\Symuns[]of\Symuns[]naturals) %
-\tyxtstxbf[]is\tyxtstxendbf[]
-   radical\Symuns[]tuple : array\Symuns[]of\Symuns[]radicals (1 .. p\rsquo[]length);
-   \tyxtstxbf[]procedure\tyxtstxendbf[] recursively\Symuns[]enumerate (level        : %
-\tyxtstxbf[]in\tyxtstxendbf[] positive;
-                                    remainder    : \tyxtstxbf[]in%
-\tyxtstxendbf[] radical\Symuns[]list;
-                                    prev\Symuns[]element : %
-\tyxtstxbf[]in\tyxtstxendbf[] natural) \tyxtstxbf[]is%
-\tyxtstxendbf[]
-      levels\Symuns[]radical\Symuns[]list : radical\Symuns[]list;
-   \tyxtstxbf[]begin\tyxtstxendbf[]
-      \tyxtstxbf[]if\tyxtstxendbf[] p(level) = prev\Symuns[]element %
-\tyxtstxbf[]then\tyxtstxendbf[]
-         levels\Symuns[]radical\Symuns[]list := remainder;
-      \tyxtstxbf[]else\tyxtstxendbf[]
-         levels\Symuns[]radical\Symuns[]list := r\Symuns[]array(p(level));
-      \tyxtstxbf[]end\tyxtstxendbf[] \tyxtstxbf[]if%
-\tyxtstxendbf[];
-      \tyxtstxbf[]while\tyxtstxendbf[] \tyxtstxbf[]not%
-\tyxtstxendbf[] is\Symuns[]empty(levels\Symuns[]radical\Symuns[]list) %
-\tyxtstxbf[]loop\tyxtstxendbf[]
-         radical\Symuns[]tuple(level) := head(levels\Symuns[]radical\Symuns[]list);
-         \tyxtstxbf[]if\tyxtstxendbf[] level \Symlt[] p\rsquo[]length %
-\tyxtstxbf[]then\tyxtstxendbf[]
-            recursively\Symuns[]enumerate (level + 1,
-                                   levels\Symuns[]radical\Symuns[]list,
-                                   p(level));
-         \tyxtstxbf[]else\tyxtstxendbf[]
-            apply\Symuns[]to\Symuns[]each (radical\Symuns[]tuple);
-         \tyxtstxbf[]end\tyxtstxendbf[] \tyxtstxbf[]if%
-\tyxtstxendbf[];
-         levels\Symuns[]radical\Symuns[]list := tail(levels\Symuns[]radical\Symuns[]list);
-      \tyxtstxbf[]end\tyxtstxendbf[] \tyxtstxbf[]loop%
-\tyxtstxendbf[];
-   \tyxtstxbf[]end\tyxtstxendbf[];
-\tyxtstxbf[]begin\tyxtstxendbf[]
-   recursively\Symuns[]enumerate (1, r\Symuns[]array(p(1)), p(1));
-\tyxtstxbf[]end\tyxtstxendbf[];\Endcomp[]
-\EndParbox[]
-\FgEndblock[]
- It has a structure similar to \tyxffmxmono[]enum\Symuns[]partitions%
-\tyxffmxendmono[]. An inner procedure, \tyxffmxmono[]recursively\Symuns[]enumerate%
-\tyxffmxendmono[], is called to assign the first element of the radical
-tuple; it calls itself recursively to assign successive elements,
-until the last element is reached. At each level of recursion, it
-determines the list of radicals available for assignments at that
-level, and it loops through those values (ascending to the next higher
-level for each in turn); that list is the entire list of radicals
-of the size needed for the level, unless the level has the same size
-as the previous level, in which case the list is \txtxemph[]the remaining
-portion\txtxendemph[] of the list from the previous level, starting
-from the radical that was assigned at the previous level.%
-\NtFoot[]\NtNtpar[]This is a subtle consequence of the need to deliver
-a tuple of lexicographically ordered radicals.\NtEndntpar[]%
-\NtEndfoot[] At the highest level, when a tuple has been enumerated,
-it applies the operation passed parametrically to the tuple.%
-\Endpara[]
-\Para[]Finally, it is worth emphasizing that the trees we construct
-to represent radicals and molecules share components. Thus, the subradicals
-of a radical do not occupy storage independently from their occurrences
-as top-level radicals in their own right, or from other occurrences
-of themselves as subradicals of a different radical. The creation
-of a new radical does not require the copying of subradicals, nor
-does the creation of a molecule require the copying of radicals; they
-require only the allocation of a single new root node, which is initialized
-with pointers to the appropriate subnodes. Each radical is, in general,
-pointed to many times. Only one instance of the hydrogen radical is
-created.\Endpara[]
-\DivEndiv[]
-\DivLiv[]\HdMinLiv[]Parallel Solution\HdMinEndiv[]
-\Para[]There are many ways that one could introduce explicit parallelism,
-if one desired, to gain speedup. The most obvious and straightforward
-way is to perform all the iterations of the molecule-constructing
-loop of \tyxffmxmono[]paraffins\tyxffmxendmono[] in parallel (say,
-each by a separate task), since the list of paraffin molecules of
-size \InlEqn[]\LmthEqn[]i
-\LmthEndeqn[]\EndInlEqn[] is completely independent of the list for
-any other size.\NtFoot[]\NtNtpar[]Admittedly, this strategy does not
-have good load-balancing properties. One could get by with fewer tasks,
-since one task could create several lists of molecules of small size
-sequentially in the time that it takes another task to create a list
-of molecules of large size.\NtEndntpar[]\NtEndfoot[] However, it is
-not necessary to wait until all the radical lists are complete before
-starting on the molecule lists. Since molecules of size %
-\InlEqn[]\LmthEqn[]i
-\LmthEndeqn[]\EndInlEqn[] involve radicals of sizes not larger than %
-\InlEqn[]\LmthEqn[]
-\left\lfloor {{{i-1} \over {2}}}
-\right\rfloor 
-\LmthEndeqn[]\EndInlEqn[], it is possible to start the generation of molecules
-of size \InlEqn[]\LmthEqn[]2i
-\LmthEndeqn[]\EndInlEqn[] (if \InlEqn[]\LmthEqn[]i>0
-\LmthEndeqn[]\EndInlEqn[]) and those
-of size \InlEqn[]\LmthEqn[]2i+1
-\LmthEndeqn[]\EndInlEqn[] (if \InlEqn[]\LmthEqn[]2i<n
-\LmthEndeqn[]\EndInlEqn[]) as soon as
-the radicals of size \InlEqn[]\LmthEqn[]i
-\LmthEndeqn[]\EndInlEqn[] are finished. A parallel
-version of the \tyxffmxmono[]paraffins\tyxffmxendmono[] function capitalizing
-on this observation is shown in Figure \Xref[\def\XrefName{body-of-paraffins-parallel}].
-\FgBlock[\def\FgBlockPlace{H}]
-\Parbox[]
-\FgCap[\def\FgCapId{body-of-paraffins-parallel}]Self-specifying body
-of the \tyxffmxmono[]paraffins\tyxffmxendmono[] function (parallel
-version)\FgEndcap[]
-\Comp[]\tyxtstxbf[]with\tyxtstxendbf[] radicals, molecules;
-\tyxtstxbf[]use\tyxtstxendbf[]  radicals, molecules;
-\tyxtstxbf[]function\tyxtstxendbf[] paraffins (n : positive) %
-\tyxtstxbf[]return\tyxtstxendbf[] array\Symuns[]of\Symuns[]molecule\Symuns[]lists %
-\tyxtstxbf[]is\tyxtstxendbf[]
-   \tyxtstxbf[]type\tyxtstxendbf[] array\Symuns[]of\Symuns[]naturals %
-\tyxtstxbf[]is\tyxtstxendbf[] \tyxtstxbf[]array\tyxtstxendbf[] (positive %
-\tyxtstxbf[]range\tyxtstxendbf[] \Symlt[]\Symgt[]) \tyxtstxbf[]of%
-\tyxtstxendbf[] natural;
-   \tyxtstxbf[]use\tyxtstxendbf[] radical\Symuns[]lists, molecule\Symuns[]lists;
-   r\Symuns[]array : array\Symuns[]of\Symuns[]radical\Symuns[]lists  (0 .. n/2);
-   m\Symuns[]array : array\Symuns[]of\Symuns[]molecule\Symuns[]lists (1 .. n);
-   \tyxtstxbf[]generic\tyxtstxendbf[]
-      \tyxtstxbf[]with\tyxtstxendbf[] \tyxtstxbf[]procedure%
-\tyxtstxendbf[] apply\Symuns[]to\Symuns[]each (tuple : %
-\tyxtstxbf[]in\tyxtstxendbf[] array\Symuns[]of\Symuns[]radicals);
-   \tyxtstxbf[]procedure\tyxtstxendbf[] enum\Symuns[]rad\Symuns[]tuples (p : %
-\tyxtstxbf[]in\tyxtstxendbf[] array\Symuns[]of\Symuns[]naturals);
-   \tyxtstxbf[]task\tyxtstxendbf[] type worker\Symuns[]task %
-\tyxtstxbf[]is\tyxtstxendbf[]
-      \tyxtstxbf[]entry\tyxtstxendbf[] start\Symuns[]on\Symuns[]size (i : %
-\tyxtstxbf[]in\tyxtstxendbf[] positive);
-   \tyxtstxbf[]end\tyxtstxendbf[];
-   \tyxtstxbf[]procedure\tyxtstxendbf[] enum\Symuns[]rad\Symuns[]tuples (p : %
-\tyxtstxbf[]in\tyxtstxendbf[] array\Symuns[]of\Symuns[]naturals)  %
-\tyxtstxbf[]is\tyxtstxendbf[] \tyxtstxbf[]separate%
-\tyxtstxendbf[];
-   \tyxtstxbf[]procedure\tyxtstxendbf[] generate\Symuns[]radicals\Symuns[]of\Symuns[]size (i : %
-\tyxtstxbf[]in\tyxtstxendbf[] positive) \tyxtstxbf[]is%
-\tyxtstxendbf[] \tyxtstxbf[]separate\tyxtstxendbf[];
-   \tyxtstxbf[]procedure\tyxtstxendbf[] generate\Symuns[]ccps\Symuns[]of\Symuns[]size     (i : %
-\tyxtstxbf[]in\tyxtstxendbf[] positive) \tyxtstxbf[]is%
-\tyxtstxendbf[] \tyxtstxbf[]separate\tyxtstxendbf[];
-   \tyxtstxbf[]procedure\tyxtstxendbf[] generate\Symuns[]bcps\Symuns[]of\Symuns[]size     (i : %
-\tyxtstxbf[]in\tyxtstxendbf[] positive) \tyxtstxbf[]is%
-\tyxtstxendbf[] \tyxtstxbf[]separate\tyxtstxendbf[];
-   \tyxtstxbf[]task\tyxtstxendbf[] \tyxtstxbf[]body%
-\tyxtstxendbf[] worker\Symuns[]task                                 %
-\tyxtstxbf[]is\tyxtstxendbf[] \tyxtstxbf[]separate%
-\tyxtstxendbf[];
-\tyxtstxbf[]begin\tyxtstxendbf[]
-   \tyxtstxbf[]declare\tyxtstxendbf[]
-      molecule\Symuns[]list\Symuns[]generator : \tyxtstxbf[]array%
-\tyxtstxendbf[] (1 .. n) \tyxtstxbf[]of\tyxtstxendbf[] worker\Symuns[]task;
-   \tyxtstxbf[]begin\tyxtstxendbf[]
-      append (hydrogen\Symuns[]radical, to =\Symgt[] r\Symuns[]array(0));
-      molecule\Symuns[]list\Symuns[]generator(1).start\Symuns[]on\Symuns[]size (1);
-      \tyxtstxbf[]for\tyxtstxendbf[] i \tyxtstxbf[]in%
-\tyxtstxendbf[] 1 .. n/2 \tyxtstxbf[]loop\tyxtstxendbf[]
-         generate\Symuns[]radicals\Symuns[]of\Symuns[]size (i);
-         molecule\Symuns[]list\Symuns[]generator(2*i).start\Symuns[]on\Symuns[]size (2*i);
-         \tyxtstxbf[]if\tyxtstxendbf[] 2*i \Symlt[] n %
-\tyxtstxbf[]then\tyxtstxendbf[]
-            molecule\Symuns[]list\Symuns[]generator(2*i+1).start\Symuns[]on\Symuns[]size (2*i+1);
-         \tyxtstxbf[]end\tyxtstxendbf[] \tyxtstxbf[]if%
-\tyxtstxendbf[];
-      \tyxtstxbf[]end\tyxtstxendbf[] \tyxtstxbf[]loop%
-\tyxtstxendbf[];
-   \tyxtstxbf[]end\tyxtstxendbf[];
-   \tyxtstxbf[]return\tyxtstxendbf[] m\Symuns[]array;
-\tyxtstxbf[]end\tyxtstxendbf[];\Endcomp[]
-\EndParbox[]
-\FgEndblock[]
- The only additions to the declarative part of the function are the
-specification and body stub of a task type, \tyxffmxmono[]worker\Symuns[]task%
-\tyxffmxendmono[], whose proper body is shown in the next figure.
-The block statement in the statement list of the function declares
-an array, \tyxffmxmono[]molecule\Symuns[]list\Symuns[]generator%
-\tyxffmxendmono[], of tasks of the type \tyxffmxmono[]worker\Symuns[]task%
-\tyxffmxendmono[], all of which wait for a rendezvous with their %
-\tyxffmxmono[]start\Symuns[]on\Symuns[]size\tyxffmxendmono[] entry
-before proceeding. The block statement then sequentially creates the
-radical lists and, as each is completed, signals one or two of the
-tasks to start on their molecule lists; it does not wait at that point
-for those tasks to complete. Each task continues without any further
-interaction until it completes. The block statement waits at its end
-until all of its dependent tasks have completed; then the return statement
-is finally executed.\Endpara[]
-\Para[]The proper body of the \tyxffmxmono[]worker\Symuns[]task%
-\tyxffmxendmono[] task is shown in Figure \Xref[\def\XrefName{body-of-worker-task}].
-After receiving its signal to proceed, during which it records the
-size of the molecules
-\FgBlock[\def\FgBlockPlace{H}]
-\Parbox[]
-\FgCap[\def\FgCapId{body-of-worker-task}]Proper body of the %
-\tyxffmxmono[]worker\Symuns[]task\tyxffmxendmono[] task%
-\FgEndcap[]
-\Comp[]\tyxtstxbf[]separate\tyxtstxendbf[] (paraffins)
-\tyxtstxbf[]task\tyxtstxendbf[] \tyxtstxbf[]body\tyxtstxendbf[] worker\Symuns[]task %
-\tyxtstxbf[]is\tyxtstxendbf[]
-   my\Symuns[]size : positive;
-\tyxtstxbf[]begin\tyxtstxendbf[]
-   \tyxtstxbf[]accept\tyxtstxendbf[] start\Symuns[]on\Symuns[]size (i : %
-\tyxtstxbf[]in\tyxtstxendbf[] positive) \tyxtstxbf[]do%
-\tyxtstxendbf[]
-      my\Symuns[]size := i;
-   \tyxtstxbf[]end\tyxtstxendbf[];
-   generate\Symuns[]ccps\Symuns[]of\Symuns[]size (my\Symuns[]size);
-   \tyxtstxbf[]if\tyxtstxendbf[] my\Symuns[]size \tyxtstxbf[]mod%
-\tyxtstxendbf[] 2 = 0 \tyxtstxbf[]then\tyxtstxendbf[]
-      generate\Symuns[]bcps\Symuns[]of\Symuns[]size (my\Symuns[]size);
-   \tyxtstxbf[]end\tyxtstxendbf[] \tyxtstxbf[]if\tyxtstxendbf[];
-\tyxtstxbf[]end\tyxtstxendbf[];\Endcomp[]
-\EndParbox[]
-\FgEndblock[]
- on which it is to work, the task simply calls \tyxffmxmono[]generate\Symuns[]ccps\Symuns[]of\Symuns[]size%
-\tyxffmxendmono[] to generate the CCPs of its size. Following that,
-if its size is even, it calls \tyxffmxmono[]generate\Symuns[]bcps\Symuns[]of\Symuns[]size%
-\tyxffmxendmono[] to generate the BCPs of that size. Of course, the
-BCPs and CCPs of a given size are also independent of each other and
-could be constructed in parallel. As it stands, our program is not
-so amenable to that, but one can imagine simple changes that would
-facilitate further enhancement.\Endpara[]
-\Para[]Applicative languages have an obvious advantage over Ada\EmDash[]namely,
-that opportunities for parallelism such as we have seized here (and
-others on a more microscopic scale) are exploited implicitly and automatically
-to the extent permitted by the dataflow properties of the problem
-at hand.\Endpara[]
-\DivEndiv[]
-\DivEndiii[]
-\DivLiii[]\HdMjLiii[]The Doctor\rsquo[]s Office Problem%
-\HdMjEndiii[]
-\Para[]Given a set of patients, a set of doctors, and a receptionist,
-the problem is to model the following interactions. Initially, all
-patients are well, and all doctors are in a queue waiting to treat
-sick patients. At random times, patients become sick and enter a queue
-for treatment by one of the doctors. The receptionist handles the
-two queues, assigning patients to doctors in a FIFO manner. Once a
-doctor and patient are paired, the doctor diagnoses the illness and,
-in a randomly chosen period of time, cures the patient. Then, the
-doctor and patient return to the receptionist\rsquo[]s desk, where
-the receptionist records pertinent information. The patient is then
-released until such time as he or she becomes sick again, and the
-doctor returns to the queue to await another patient. Any distribution
-functions may be used for the patients\rsquo[] healthy times and doctors\rsquo[]
-cure times, but the code that models doctors must have no knowledge
-of the distribution function for patients, and vice versa, and that
-for the receptionist should know nothing of either.\Endpara[]
-\Para[]The doctor\rsquo[]s office problem seems tailor-made for Ada;
-in fact, the solution is so concise that it is greatly eclipsed by
-our discussion of it. The solution employs a collection of tasks interacting
-in ways that model the interactions of the patients, doctors, and
-receptionist as defined in the problem statement; indeed, there is
-a receptionist task and one task for each patient and each doctor.
-No difficulties are encountered in constructing the model in Ada;
-in particular, Ada allows the task modeling the receptionist to respond
-directly to interactions initiated by either patient or doctor tasks,
-with no regard to which occurs first. Some other languages have difficulty
-responding asynchronously to signals from a union of dissimilar sources.%
-\Endpara[]
-\DivLiv[]\HdMinLiv[]Characteristics of Alternative Approaches%
-\HdMinEndiv[]
-\Para[]This problem can be solved in either of two distinctly different
-ways. One can write a \ldquo[]real-time program,\rdquo[] in which
-the periods of health and sickness are modeled by the suspension of
-patient (or, in the latter case, both patient and doctor) tasks for
-directly proportional periods of real time. Or, one can write a \ldquo[]discrete-event
-simulation program,\rdquo[] in which the time to the next scheduled
-\ldquo[]event\rdquo[] (such as the expiration of a healthy period)
-is elided. In the former, the interacting tasks spend most of their
-time waiting for the expiration of one delay or another; and since
-they will all typically be doing so simultaneously, the program as
-a whole runs very inefficiently. The latter approach is far more efficient,
-since whenever all the tasks would otherwise be waiting for the expiration
-of various delays, the clock is effectively reset instantaneously
-to the time at which the next delay is due to expire. The program
-as a whole is consequently never in the \ldquo[]wait state,\rdquo[]
-and its total duration is dominated not by the lengths of the simulated
-waits but rather by the number of simulated nonwaiting events and
-the computational resources required to model each one of them.%
-\Endpara[]
-\Para[]Both approaches have in common the need to suspend individual
-tasks for some period of time before they can proceed with their next
-action. (In the real-time program, tasks are suspended for a predetermined
-amount of time that is not influenced by what other tasks do during
-the wait; in the discrete-event simulation, tasks are suspended for
-an amount of time not known in advance, the suspension ending at a
-moment determined by what all the tasks do until then). Thus, as far
-as the logical behavior of each task is concerned, there is very little
-difference between the two approaches: tasks interact with each other
-and occasionally become suspended until awakened by the expiration
-of a delay or by a rendezvous. Since the interactions and suspensions
-to be modeled are adequately and equally demonstrated by either approach,
-we have chosen the simpler (albeit less efficient) approach involving
-a real-time program. The discrete-event simulation would have the
-added complexity of an ordered-time-queue manager, which is neither
-germane to the problem nor instrumental in determining the interactions
-among the other tasks. The real-time program can be changed to a discrete-event
-simulation merely by making systematic, local changes at all the places
-where a delay statement is found and adding an ordered-time-queue
-manager component; the details are omitted for lack of space.%
-\Endpara[]
-\Para[]The problem statement does not say anything about when or how
-the modeling of the doctor\rsquo[]s office is to end; presumably,
-such details only complicate the essential behavior to be demonstrated.
-In that spirit, we have simplified our solution by ignoring termination
-questions; the modeled interactions continue forever. Termination
-can, of course, be designed in, after one defines appropriate termination
-criteria; depending on the criteria adopted, achieving termination
-might require additional communication among some of the tasks.%
-\Endpara[]
-\DivEndiv[]
-\DivLiv[]\HdMinLiv[]Structure of the Solution\HdMinEndiv[]
-\Para[]The solution presented here is in the form of a generic procedure
-called \tyxffmxmono[]doctors\Symuns[]office\tyxffmxendmono[]. The
-generic procedure is parameterized by two function subprograms, which
-are random-number generators for selecting the random periods of health
-enjoyed by each patient and the intervening random periods of diagnosis
-and cure (once the patient has been assigned a doctor). The specification
-for the generic procedure is shown in Figure \Xref[\def\XrefName{spec-of-doctors-office}].
-\FgBlock[\def\FgBlockPlace{H}]
-\Parbox[]
-\FgCap[\def\FgCapId{spec-of-doctors-office}]Specification of the %
-\tyxffmxmono[]doctors\Symuns[]office\tyxffmxendmono[] generic procedure%
-\FgEndcap[]
-\Comp[]\tyxtstxbf[]generic\tyxtstxendbf[]
-   \tyxtstxbf[]with\tyxtstxendbf[] \tyxtstxbf[]function%
-\tyxtstxendbf[] random\Symuns[]healthy\Symuns[]period   %
-\tyxtstxbf[]return\tyxtstxendbf[] duration;
-   \tyxtstxbf[]with\tyxtstxendbf[] \tyxtstxbf[]function%
-\tyxtstxendbf[] random\Symuns[]treatment\Symuns[]period %
-\tyxtstxbf[]return\tyxtstxendbf[] duration;
-\tyxtstxbf[]procedure\tyxtstxendbf[] doctors\Symuns[]office (number\Symuns[]of\Symuns[]patients : %
-\tyxtstxbf[]in\tyxtstxendbf[] natural;
-                          number\Symuns[]of\Symuns[]doctors  : %
-\tyxtstxbf[]in\tyxtstxendbf[] natural);\Endcomp[]
-\EndParbox[]
-\FgEndblock[]
- To use this machinery, one instantiates the generic procedure, supplying
-the names of the two random-number generators, to get a (nongeneric)
-procedure, which one then calls with two actual parameters representing
-the number of patients and number of doctors.\Endpara[]
-\Para[]In the solution, we use the predefined fixed-point type %
-\tyxffmxmono[]duration\tyxffmxendmono[] for the result of the random-number
-generators, since that is the type required for the operand of a delay
-statement, where the result is used. We use the predefined subtype
-\tyxffmxmono[]natural\tyxffmxendmono[] of the predefined type %
-\tyxffmxmono[]integer\tyxffmxendmono[] for the number of patients
-and number of doctors. The body of the generic procedure is shown
-in Figure \Xref[\def\XrefName{body-of-doctors-office}].
-\FgBlock[]
-\Parbox[]
-\FgCap[\def\FgCapId{body-of-doctors-office}]Body of the %
-\tyxffmxmono[]doctors\Symuns[]office\tyxffmxendmono[] generic procedure%
-\FgEndcap[]
-\Comp[]\tyxtstxbf[]procedure\tyxtstxendbf[] doctors\Symuns[]office (number\Symuns[]of\Symuns[]patients : %
-\tyxtstxbf[]in\tyxtstxendbf[] natural;
-                          number\Symuns[]of\Symuns[]doctors  : %
-\tyxtstxbf[]in\tyxtstxendbf[] natural) \tyxtstxbf[]is%
-\tyxtstxendbf[]
-   \tyxtstxbf[]task\tyxtstxendbf[] \tyxtstxbf[]type%
-\tyxtstxendbf[] patient\Symuns[]task;
-   \tyxtstxbf[]type\tyxtstxendbf[] doctor\Symuns[]task;
-   \tyxtstxbf[]type\tyxtstxendbf[] doctor \tyxtstxbf[]is%
-\tyxtstxendbf[] \tyxtstxbf[]access\tyxtstxendbf[] doctor\Symuns[]task;
-   \tyxtstxbf[]task\tyxtstxendbf[] \tyxtstxbf[]type%
-\tyxtstxendbf[] doctor\Symuns[]task \tyxtstxbf[]is%
-\tyxtstxendbf[]
-      \tyxtstxbf[]entry\tyxtstxendbf[] identify\Symuns[]self (myself : %
-\tyxtstxbf[]in\tyxtstxendbf[] doctor);
-      \tyxtstxbf[]entry\tyxtstxendbf[] patient\Symuns[]visiting\Symuns[]for\Symuns[]treatment;
-   \tyxtstxbf[]end\tyxtstxendbf[];
-   \tyxtstxbf[]task\tyxtstxendbf[] receptionist \tyxtstxbf[]is%
-\tyxtstxendbf[]
-      \tyxtstxbf[]entry\tyxtstxendbf[] patient\Symuns[]becoming\Symuns[]sick;
-      \tyxtstxbf[]entry\tyxtstxendbf[] doctor\Symuns[]requesting\Symuns[]patient (d1 : %
-\tyxtstxbf[]in\tyxtstxendbf[]  doctor);
-      \tyxtstxbf[]entry\tyxtstxendbf[] patient\Symuns[]requesting\Symuns[]doctor (d2 : %
-\tyxtstxbf[]out\tyxtstxendbf[] doctor);
-   \tyxtstxbf[]end\tyxtstxendbf[];
-   patient    : \tyxtstxbf[]array\tyxtstxendbf[] (1 .. number\Symuns[]of\Symuns[]patients) %
-\tyxtstxbf[]of\tyxtstxendbf[] patient\Symuns[]task;
-   new\Symuns[]doctor : doctor;
-   \tyxtstxbf[]task\tyxtstxendbf[] \tyxtstxbf[]body%
-\tyxtstxendbf[] patient\Symuns[]task \tyxtstxbf[]is%
-\tyxtstxendbf[] \tyxtstxbf[]separate\tyxtstxendbf[];
-   \tyxtstxbf[]task\tyxtstxendbf[] \tyxtstxbf[]body%
-\tyxtstxendbf[] doctor\Symuns[]task  \tyxtstxbf[]is%
-\tyxtstxendbf[] \tyxtstxbf[]separate\tyxtstxendbf[];
-   \tyxtstxbf[]task\tyxtstxendbf[] \tyxtstxbf[]body%
-\tyxtstxendbf[] receptionist \tyxtstxbf[]is\tyxtstxendbf[] %
-\tyxtstxbf[]separate\tyxtstxendbf[];
-\tyxtstxbf[]begin\tyxtstxendbf[]
-   \tyxtstxbf[]for\tyxtstxendbf[] i \tyxtstxbf[]in%
-\tyxtstxendbf[] 1 .. number\Symuns[]of\Symuns[]doctors %
-\tyxtstxbf[]loop\tyxtstxendbf[]
-      new\Symuns[]doctor := \tyxtstxbf[]new\tyxtstxendbf[] doctor\Symuns[]task;
-      new\Symuns[]doctor.identify\Symuns[]self (new\Symuns[]doctor);
-   \tyxtstxbf[]end\tyxtstxendbf[] \tyxtstxbf[]loop%
-\tyxtstxendbf[];
-\tyxtstxbf[]end\tyxtstxendbf[];\Endcomp[]
-\EndParbox[]
-\FgEndblock[]
- Places for the bodies of the task types \tyxffmxmono[]patient\Symuns[]task%
-\tyxffmxendmono[] and \tyxffmxmono[]doctor\Symuns[]task%
-\tyxffmxendmono[] and for the single task \tyxffmxmono[]receptionist%
-\tyxffmxendmono[] are held by body stubs, whose corresponding proper
-bodies are shown later.\Endpara[]
-\Para[]Note that the collection of patients is managed differently
-from the collection of doctors. In our solution, patients perform
-entry calls\NtFoot[]\NtNtpar[]For convenience throughout the remainder
-of this section, we refer to objects of type \tyxffmxmono[]patient\Symuns[]task%
-\tyxffmxendmono[] as \ldquo[]patients,\rdquo[] objects of type %
-\tyxffmxmono[]doctor\Symuns[]task\tyxffmxendmono[] as \ldquo[]doctors,\rdquo[]
-and the single \tyxffmxmono[]receptionist\tyxffmxendmono[] task as
-\ldquo[]the receptionist\rdquo[] when discussing the behavior of our
-program units. We occasionally use the same words to refer to the
-people that they model, as when we discuss the problem statement.%
-\NtEndntpar[]\NtEndfoot[] but have no need to accept them; since no
-task calls an entry of a patient, the identity of any individual patient
-is never needed. The easiest and most straightforward way of allocating
-the required number of patients is to declare an array of %
-\tyxffmxmono[]patient\Symuns[]task\tyxffmxendmono[]s having the appropriate
-bounds; subscripted components of this array are never referenced.
-Doctors, on the other hand, both perform and accept entry calls, so
-there \txtxemph[]is\txtxendemph[] a need to identify individual doctors.
-We choose to identify them by allocating each one individually, obtaining
-a pointer to the newly allocated \tyxffmxmono[]doctor\Symuns[]task%
-\tyxffmxendmono[] and then passing that pointer value to the task
-itself (via its \tyxffmxmono[]identify\Symuns[]self%
-\tyxffmxendmono[] entry), which saves it in a task-local variable;
-no collective record of all the doctors is retained outside of them,
-because none is needed. A doctor passes its own identity to the receptionist
-when it becomes free and requests a patient to treat. The receptionist
-accepts such a call from a doctor only when some patient is sick,
-at which time it passes the doctor\rsquo[]s identity on to the patient,
-who then interacts with the doctor to receive treatment.%
-\Endpara[]
-\Para[]After the allocation and initialization of all the doctors,
-all the subsequent action occurs inside the dependent tasks of %
-\tyxffmxmono[]doctors\Symuns[]office\tyxffmxendmono[]; consequently,
-before returning to its caller, \tyxffmxmono[]doctors\Symuns[]office%
-\tyxffmxendmono[] waits (at its end) for all its dependent tasks to
-terminate. Since they never do, in this implementation, %
-\tyxffmxmono[]doctors\Symuns[]office\tyxffmxendmono[] never returns.%
-\Endpara[]
-\DivEndiv[]
-\DivLiv[]\HdMinLiv[]Behavior of Patients\HdMinEndiv[]
-\Para[]The code implementing the behavior of patients is shown in
-Figure \Xref[\def\XrefName{body-of-patient}]. A patient\rsquo[]s behavior
-is very simple. Repetitively, a patient enjoys a random period of
-health,
-\FgBlock[\def\FgBlockPlace{H}]
-\Parbox[]
-\FgCap[\def\FgCapId{body-of-patient}]Proper body of the %
-\tyxffmxmono[]patient\Symuns[]task\tyxffmxendmono[] task type%
-\FgEndcap[]
-\Comp[]\tyxtstxbf[]separate\tyxtstxendbf[] (doctors\Symuns[]office)
-\tyxtstxbf[]task\tyxtstxendbf[] \tyxtstxbf[]body\tyxtstxendbf[] patient\Symuns[]task %
-\tyxtstxbf[]is\tyxtstxendbf[]
-   assigned\Symuns[]doctor : doctor;
-\tyxtstxbf[]begin\tyxtstxendbf[]
-   \tyxtstxbf[]loop\tyxtstxendbf[]
-      \tyxtstxbf[]delay\tyxtstxendbf[] random\Symuns[]healthy\Symuns[]period;
-      receptionist.patient\Symuns[]becoming\Symuns[]sick;
-      receptionist.patient\Symuns[]requesting\Symuns[]doctor (assigned\Symuns[]doctor);
-      assigned\Symuns[]doctor.patient\Symuns[]visiting\Symuns[]for\Symuns[]treatment;
-   \tyxtstxbf[]end\tyxtstxendbf[] \tyxtstxbf[]loop%
-\tyxtstxendbf[];
-\tyxtstxbf[]end\tyxtstxendbf[];\Endcomp[]
-\EndParbox[]
-\FgEndblock[]
- checks in with the receptionist (announcing sickness), requests from
-the receptionist the services of a doctor, is assigned a doctor when
-one becomes available, and visits the doctor to receive treatment.
-The problem statement says that, after the cure, the patient and the
-doctor are to return to the receptionist; the patient does not do
-so here, simply because there is no relevant action (affecting doctors
-or patients) that the receptionist needs to take on behalf of the
-patient at that point. Depending on the record keeping expected of
-the receptionist, additional interactions with it might be desirable.%
-\Endpara[]
-\Para[]As we will see upon examining the detailed behavior of the
-receptionist, the call that a patient makes to inform the receptionist
-of sickness does not cause an indefinite suspension of the patient;
-it might cause a very brief suspension (i.e., if the receptionist
-is currently occupied), akin to the wait for a monitor lock. The point
-to note is that the receptionist is designed so that, each time through
-its loop, it is receptive to a call from a patient to its %
-\tyxffmxmono[]patient\Symuns[]becoming\Symuns[]sick%
-\tyxffmxendmono[] entry. On the other hand, a patient might very well
-become suspended when it immediately thereafter calls the receptionist
-at the latter\rsquo[]s \tyxffmxmono[]patient\Symuns[]requesting\Symuns[]doctor%
-\tyxffmxendmono[] entry, since the receptionist might not be in a
-state in which it is executing (or can execute) its accept statement
-for that entry. The availability of a doctor is a prerequisite to
-the execution of that accept statement. Eventually a doctor will become
-available to treat the patient (patients remain suspended not just
-until a doctor becomes available, but also until all prior requests
-by patients for doctors have been satisfied), at which time the patient\rsquo[]s
-entry call to \tyxffmxmono[]patient\Symuns[]requesting\Symuns[]doctor%
-\tyxffmxendmono[] will result in a rendezvous with the receptionist,
-who will pass to the patient the identity of the available doctor.
-After concluding its \tyxffmxmono[]patient\Symuns[]requesting\Symuns[]doctor%
-\tyxffmxendmono[] rendezvous with the receptionist, the patient will
-straightaway call the assigned doctor at the latter\rsquo[]s %
-\tyxffmxmono[]patient\Symuns[]visiting\Symuns[]for\Symuns[]treatment%
-\tyxffmxendmono[] entry, remaining suspended in a rendezvous until
-the cure has been effected.\Endpara[]
-\DivEndiv[]
-\DivLiv[]\HdMinLiv[]Behavior of Doctors\HdMinEndiv[]
-\Para[]The code implementing the behavior of doctors is shown in Figure
-\Xref[\def\XrefName{body-of-doctor}]. The repetitive behavior of a
-doctor, after receiving and storing its own identity,
-\FgBlock[\def\FgBlockPlace{H}]
-\Parbox[]
-\FgCap[\def\FgCapId{body-of-doctor}]Proper body of the %
-\tyxffmxmono[]doctor\Symuns[]task\tyxffmxendmono[] task type%
-\FgEndcap[]
-\Comp[]\tyxtstxbf[]separate\tyxtstxendbf[] (doctors\Symuns[]office)
-\tyxtstxbf[]task\tyxtstxendbf[] \tyxtstxbf[]body\tyxtstxendbf[] doctor\Symuns[]task %
-\tyxtstxbf[]is\tyxtstxendbf[]
-   self : doctor;
-\tyxtstxbf[]begin\tyxtstxendbf[]
-   \tyxtstxbf[]accept\tyxtstxendbf[] identify\Symuns[]self (myself : %
-\tyxtstxbf[]in\tyxtstxendbf[] doctor) \tyxtstxbf[]do%
-\tyxtstxendbf[]
-      self := myself;
-   \tyxtstxbf[]end\tyxtstxendbf[];
-   \tyxtstxbf[]loop\tyxtstxendbf[]
-      receptionist.doctor\Symuns[]requesting\Symuns[]patient (self);
-      \tyxtstxbf[]accept\tyxtstxendbf[] patient\Symuns[]visiting\Symuns[]for\Symuns[]treatment %
-\tyxtstxbf[]do\tyxtstxendbf[]
-         \tyxtstxbf[]delay\tyxtstxendbf[] random\Symuns[]treatment\Symuns[]period;
-      \tyxtstxbf[]end\tyxtstxendbf[];
-   \tyxtstxbf[]end\tyxtstxendbf[] \tyxtstxbf[]loop%
-\tyxtstxendbf[];
-\tyxtstxbf[]end\tyxtstxendbf[];\Endcomp[]
-\EndParbox[]
-\FgEndblock[]
- is to announce to the receptionist its availability to treat patients,
-then (once a patient has come to it for treatment) to render service
-in the form of a treatment that takes a random period of time. The
-problem statement says that a doctor (as well as its patient) returns
-to the receptionist at the conclusion of treatment; the doctor\rsquo[]s
-return to the receptionist, at least, is adequately modeled by our
-solution, because after treating a patient the doctor\rsquo[]s next
-action is to inform the receptionist immediately that it is again
-available to treat patients. An additional interaction with the receptionist
-could be programmed (at the bottom of the loop) to signal, for record-keeping
-purposes, the doctor\rsquo[]s conclusion of treatment, but there is
-no relevant action (affecting doctors or patients) that the receptionist
-needs to take on behalf of the doctor at that point.\Endpara[]
-\Para[]As we will see upon examining the detailed behavior of the
-receptionist, a doctor might very well become suspended when it calls
-the receptionist to request a patient, since the receptionist is not
-always receptive to such calls; that happens when no patient is sick
-and is an essential part of the behavior to be modeled. Eventually
-a patient becomes sick (the doctor remains suspended not just until
-a patient becomes sick, but also until all prior requests for patients
-by doctors have been satisfied), at which time the doctor\rsquo[]s
-entry call to \tyxffmxmono[]doctor\Symuns[]requesting\Symuns[]patient%
-\tyxffmxendmono[] will result in a rendezvous with the receptionist,
-who will receive the identity of the doctor. The receptionist passes
-that identity to the patient with whom the doctor is being paired,
-and the patient calls the doctor so identified (at the doctor\rsquo[]s
-\tyxffmxmono[]patient\Symuns[]visiting\Symuns[]for\Symuns[]treatment%
-\tyxffmxendmono[] entry). Thus, after completing its rendezvous with
-the receptionist, the doctor will treat a patient without further
-delay. Finally, note that the delay statement that causes the doctor\rsquo[]s
-suspension for the duration of the treatment keeps the patient suspended
-for the same time, since that delay statement is executed as part
-of the rendezvous between patient and doctor.\Endpara[]
-\DivEndiv[]
-\DivLiv[]\HdMinLiv[]Behavior of the Receptionist\HdMinEndiv[]
-\Para[]The code implementing the behavior of the receptionist is shown
-in Figure \Xref[\def\XrefName{body-of-receptionist}].
-\FgBlock[\def\FgBlockPlace{H}]
-\Parbox[]
-\FgCap[\def\FgCapId{body-of-receptionist}]Proper body of the %
-\tyxffmxmono[]receptionist\tyxffmxendmono[] task\FgEndcap[]
-\Comp[]\tyxtstxbf[]separate\tyxtstxendbf[] (doctors\Symuns[]office)
-\tyxtstxbf[]task\tyxtstxendbf[] \tyxtstxbf[]body\tyxtstxendbf[] receptionist %
-\tyxtstxbf[]is\tyxtstxendbf[]
-   sick\Symuns[]patients : natural := 0;
-\tyxtstxbf[]begin\tyxtstxendbf[]
-   \tyxtstxbf[]loop\tyxtstxendbf[]
-      \tyxtstxbf[]select\tyxtstxendbf[]
-         \tyxtstxbf[]accept\tyxtstxendbf[] patient\Symuns[]becoming\Symuns[]sick;
-         sick\Symuns[]patients := sick\Symuns[]patients + 1;
-      \tyxtstxbf[]or\tyxtstxendbf[]
-      \tyxtstxbf[]when\tyxtstxendbf[] sick\Symuns[]patients \Symgt[] 0 =\Symgt[]
-         \tyxtstxbf[]accept\tyxtstxendbf[] doctor\Symuns[]requesting\Symuns[]patient (d1 : %
-\tyxtstxbf[]in\tyxtstxendbf[] doctor) \tyxtstxbf[]do%
-\tyxtstxendbf[]
-            \tyxtstxbf[]accept\tyxtstxendbf[] patient\Symuns[]requesting\Symuns[]doctor (d2 : %
-\tyxtstxbf[]out\tyxtstxendbf[] doctor) \tyxtstxbf[]do%
-\tyxtstxendbf[]
-               d2 := d1;
-            \tyxtstxbf[]end\tyxtstxendbf[];
-         \tyxtstxbf[]end\tyxtstxendbf[];
-         sick\Symuns[]patients := sick\Symuns[]patients - 1;
-      \tyxtstxbf[]end\tyxtstxendbf[] \tyxtstxbf[]select%
-\tyxtstxendbf[];
-   \tyxtstxbf[]end\tyxtstxendbf[] \tyxtstxbf[]loop%
-\tyxtstxendbf[];
-\tyxtstxbf[]end\tyxtstxendbf[];\Endcomp[]
-\EndParbox[]
-\FgEndblock[]
- The behavior of the receptionist is subtle, but straightforward.
-Repetitively, the receptionist just waits for, and then acts on, either
-a notification that a patient has become sick or a request by a free
-doctor for a patient to treat. The receptionist processes one patient\rsquo[]s
-notification or doctor\rsquo[]s request each time through its loop,
-waiting if necessary for one to arrive. It is always receptive to
-the notification, but it is receptive to the request only when certain
-conditions are satisfied. Specifically, it will accept the request
-by a doctor for a patient to treat only if a patient is available
-to satisfy the request (i.e., only if a patient is sick). If, on some
-iteration of the loop, no patients are awaiting treatment, then the
-receptionist will remain suspended until being notified of the arrival
-of a sick patient, even if there is an outstanding request by a doctor
-for a patient to treat.\Endpara[]
-\Para[]The wait for either of two entry calls is achieved by coding
-a selective wait inside a loop. The second of the selective wait\rsquo[]s
-two accept alternatives is, furthermore, guarded so that, on some
-iterations of the loop (in particular, those in which the guard is
-false), a call to the guarded entry will not be accepted and will
-remain queued. When the guard is true (that is, when the second selective
-wait alternative is \ldquo[]open\rdquo[]), and calls to both of the
-entries have been made, then either entry call may be accepted; the
-one not accepted will remain pending and will be accepted on a subsequent
-execution of the selective
-\TyPbrkNewp[]
- wait (i.e., on a subsequent iteration of the loop). The logical behavior
-and the correctness of the program are insensitive to the nondeterminism
-of the choice, which gives one confidence that precisely the right
-language feature is being employed here.\Endpara[]
-\Para[]It should be noted that only two selective wait alternatives,
-representing two communication channels, are needed in the selective
-wait, rather than one for each doctor and each patient. The receptionist
-handles its interactions with all the doctors identically, and likewise
-its interactions with all the patients. The two selective wait alternatives
-are used to discriminate between two reasons why other tasks might
-interact with the receptionist, rather than to identify the interacting
-tasks. When the identity of a doctor is needed, that identity is passed
-as data by the doctor, during its interaction.\Endpara[]
-\Para[]If multiple patients are sick and are requesting doctors, their
-entry calls remain queued in FIFO order by Ada, and one call is taken
-out of the queue for the \tyxffmxmono[]patient\Symuns[]requesting\Symuns[]doctor%
-\tyxffmxendmono[] entry each time the accept statement for that entry
-is executed. Thus, patients are treated in the order in which they
-requested doctors, as required by the problem statement. By the same
-token, if multiple doctors are trying to request patients from the
-receptionist, \txtxemph[]their\txtxendemph[] entry calls remain queued
-in FIFO order by Ada, and one call is taken out of the queue for the
-\tyxffmxmono[]doctor\Symuns[]requesting\Symuns[]patient%
-\tyxffmxendmono[] entry each time the accept statement for that entry
-is executed. The problem statement does not specify which of several
-available doctors should treat a patient, so our FIFO assignment of
-available doctors is only one of many that would have sufficed; this
-assignment is the easiest to provide, since it comes for free. Note
-that all the queuing required by this problem is performed implicitly
-by Ada, and no explicit maintenance of any queues is required.%
-\NtFoot[]\NtNtpar[]The solution demonstrated during the conference
-in 1988 was far less elegant; it \txtxemph[]did\txtxendemph[] involve
-explicit queuing.\NtEndntpar[]\NtEndfoot[]\Endpara[]
-\Para[]When the receptionist accepts an entry call from a doctor requesting
-a patient, which it does only when a patient is known to be sick,
-and while it is still engaged in a rendezvous with the doctor, it
-also accepts an entry call from a patient requesting a doctor (and
-performs a rendezvous with it). The receptionist thus acts as the
-intermediary through which information\EmDash[]an available doctor\rsquo[]s
-identity\EmDash[]is passed from doctor to patient. Note that, if the
-receptionist were to accept an entry call from an available doctor
-without knowing that a patient is sick (as would happen, for example,
-if the second selective wait alternative were unguarded), then the
-receptionist could become suspended at the accept statement for %
-\tyxffmxmono[]patient\Symuns[]requesting\Symuns[]doctor%
-\tyxffmxendmono[], and would indeed do so, if no patient were sick
-(i.e., no \tyxffmxmono[]patient\Symuns[]task\tyxffmxendmono[] were
-calling that entry). While that would have the desired effect of causing
-a doctor requesting a patient to become suspended when no patient
-were sick, the request could never be satisfied, because the receptionist
-would be unable to take note of a patient\rsquo[]s becoming sick.
-In fact, the program would deadlock. The use of a guard on the second
-selective wait alternative avoids this while still causing a doctor
-requesting a patient to become suspended when no patient is sick.%
-\Endpara[]
-\Para[]In summary, the \tyxffmxmono[]receptionist%
-\tyxffmxendmono[] task is characterized by a loop containing a selective
-wait, allowing the task repeatedly to wait for, and then respond to,
-any of several alternative events. Guards are used to make it unreceptive
-to the occurrence of some of those events at times, while remaining
-receptive to the occurrence of others; the latter, in fact, determine
-its receptivity to the former. This is a common and important tasking
-paradigm in Ada. It is worth noting also the use of nested accept
-statements in the \tyxffmxmono[]receptionist\tyxffmxendmono[] task,
-which illustrates the power that can be achieved through appropriate
-coupling of tasking constructs (rather than trying to record temporal
-\ldquo[]state\rdquo[] in data).\Endpara[]
-\Para[]It can be argued that the solution shown here gives patients,
-doctors, and the receptionist too much visibility to things they don\rsquo[]t
-need. We hasten to point out inspection reveals that no use is made
-of unnecessary visibility. Nevertheless, one can indeed structure
-the solution differently, so that each task sees \txtxemph[]only%
-\txtxendemph[] what it needs to know. Such a solution would make additional
-use of library packages and generic library packages to encapsulate
-the behavior of the tasks, with limited visibility provided by disciplined
-use of context clauses and by importation into the generic library
-packages. The interactions of the tasks, which is really the essence
-of this problem, would remain unchanged.\Endpara[]
-\DivEndiv[]
-\DivEndiii[]
-\DivLiii[\def\DivLiiiId{skyline}]\HdMjLiii[]The Skyline Matrix Problem%
-\HdMjEndiii[]
-\Para[]The problem is to solve the matrix equation \InlEqn[]\LmthEqn[]Ax=b
-\LmthEndeqn[]%
-\EndInlEqn[], where \InlEqn[]\LmthEqn[]A
-\LmthEndeqn[]\EndInlEqn[] is a skyline matrix of order
-\InlEqn[]\LmthEqn[]n
-\LmthEndeqn[]\EndInlEqn[] and \InlEqn[]\LmthEqn[]x
-\LmthEndeqn[]\EndInlEqn[] and \InlEqn[]\LmthEqn[]b
-\LmthEndeqn[]%
-\EndInlEqn[] are vectors of order \InlEqn[]\LmthEqn[]n
-\LmthEndeqn[]\EndInlEqn[]. Skyline matrices
-are square matrices having varying numbers of leading zeros in their
-subdiagonal rows and supradiagonal columns, and interest in such matrices
-centers on the economies that can accrue from treating them as a kind
-of sparse matrix and not storing the leading zeros. Their special
-structure suggests the use of \ldquo[]ragged arrays\rdquo[]\EmDash[]two-dimensional
-arrays (matrices) whose rows or columns do not all have the same bounds.
-The main purpose of the problem is to test whether the language has
-ragged arrays or, at least, primitive features that can be used to
-define and implement them. A secondary purpose of the problem is to
-see whether the language permits references to dimension-reducing
-cross sections of multidimensional arrays, such as (partial) rows
-or columns of matrices, and whether it permits operations on whole
-arrays.\Endpara[]
-\Para[]We solve this problem using Doolittle\rsquo[]s method of LU
-decomposition \Cit[\def\CitId{Fox:Doolittle}]\Endcit[] (a variation
-of Crout\rsquo[]s method in which L, rather than U, is unit triangular).
-In Section \Xref[\def\XrefName{crout-standard}] we present a solution
-for ordinary matrices (not having the skyline property). That solution
-reveals that Ada does not have a built-in capability for referencing
-cross sections (not to be confused with what Ada calls \ldquo[]slices,\rdquo[]
-which do not reduce dimensionality). However, since Ada has array-valued
-functions, one can define appropriate cross-section abstractions,
-at least to the extent that they are required for this problem.%
-\NtFoot[]\NtNtpar[]There is no getting around the inability to define
-an array with nonunity stride, so the closest one can come to providing
-cross sections is to define a function that returns a (partial) row
-or column of a matrix by \txtxemph[]copying\txtxendemph[] its components
-into a unity-stride vector. Fortunately, that suffices here.%
-\NtEndntpar[]\NtEndfoot[] Ada also does not have component-wise arithmetic
-operations on arrays, but such operations do not figure in the solution
-anyway. We use Ada\rsquo[]s ability to overload operators to define
-an inner-product operation denoted by the usual infix operator for
-multiplication. Then, in Section \Xref[\def\XrefName{crout-skyline}],
-we replace the type definitions for ordinary matrices by others for
-skyline matrices, and we refine the accompanying code to take account
-of the special structure of the matrices without obscuring the code\rsquo[]s
-underlying ties to Doolittle\rsquo[]s method.\Endpara[]
-\DivLiv[\def\DivLivId{crout-standard}]\HdMinLiv[]Solution for Ordinary
-Matrices\HdMinEndiv[]
-\Para[]We present in Figure \Xref[\def\XrefName{spec-of-matrices}]
-\FgBlock[\def\FgBlockPlace{H}]
-\Parbox[]
-\FgCap[\def\FgCapId{spec-of-matrices}]Specification of the %
-\tyxffmxmono[]matrices\tyxffmxendmono[] generic package%
-\FgEndcap[]
-\Comp[]\tyxtstxbf[]generic\tyxtstxendbf[]
-   \tyxtstxbf[]type\tyxtstxendbf[] float\Symuns[]type %
-\tyxtstxbf[]is\tyxtstxendbf[] \tyxtstxbf[]digits\tyxtstxendbf[] \Symlt[]\Symgt[];
-   n : \tyxtstxbf[]in\tyxtstxendbf[] positive;
-\tyxtstxbf[]package\tyxtstxendbf[] matrices \tyxtstxbf[]is%
-\tyxtstxendbf[]
-   \tyxtstxbf[]type\tyxtstxendbf[]    vector     \tyxtstxbf[]is%
-\tyxtstxendbf[] \tyxtstxbf[]array\tyxtstxendbf[] (positive %
-\tyxtstxbf[]range\tyxtstxendbf[] \Symlt[]\Symgt[]) \tyxtstxbf[]of%
-\tyxtstxendbf[] float\Symuns[]type;
-   \tyxtstxbf[]subtype\tyxtstxendbf[] n\Symuns[]vector   %
-\tyxtstxbf[]is\tyxtstxendbf[] vector (1 .. n);
-   \tyxtstxbf[]type\tyxtstxendbf[]    nxn\Symuns[]matrix %
-\tyxtstxbf[]is\tyxtstxendbf[] \tyxtstxbf[]array\tyxtstxendbf[] (1 .. n, 1 .. n) %
-\tyxtstxbf[]of\tyxtstxendbf[] float\Symuns[]type;
-   \tyxtstxbf[]function\tyxtstxendbf[] row (row\Symuns[]index : positive;
-                 of\Symuns[]matrix : nxn\Symuns[]matrix;
-                 from      : positive;
-                 to        : natural) \tyxtstxbf[]return%
-\tyxtstxendbf[] vector;
-   \tyxtstxbf[]function\tyxtstxendbf[] col (col\Symuns[]index : positive;
-                 of\Symuns[]matrix : nxn\Symuns[]matrix;
-                 from      : positive;
-                 to        : natural) \tyxtstxbf[]return%
-\tyxtstxendbf[] vector;
-   \tyxtstxbf[]function\tyxtstxendbf[] \quot[]*\quot[] (left, right : vector) %
-\tyxtstxbf[]return\tyxtstxendbf[] float\Symuns[]type;
-   \tyxtstxbf[]function\tyxtstxendbf[] solve (a : nxn\Symuns[]matrix; b : n\Symuns[]vector) %
-\tyxtstxbf[]return\tyxtstxendbf[] n\Symuns[]vector;
-\tyxtstxbf[]end\tyxtstxendbf[];\Endcomp[]
-\EndParbox[]
-\FgEndblock[]
- the specification of a generic package called \tyxffmxmono[]matrices%
-\tyxffmxendmono[] that imports a floating-point type and a positive
-number \tyxffmxmono[]n\tyxffmxendmono[] and exports types and subprograms
-for vectors and matrices of order \tyxffmxmono[]n%
-\tyxffmxendmono[] (called \tyxffmxmono[]n\Symuns[]vector%
-\tyxffmxendmono[] and \tyxffmxmono[]nxn\Symuns[]matrix%
-\tyxffmxendmono[], respectively) whose components are of the given
-floating-point type. The exported function \tyxffmxmono[]solve%
-\tyxffmxendmono[] solves the matrix problem. Different instantiations
-of this generic package are required to obtain matrices of different
-sizes. The need for multiple instantiations could have been avoided
-by defining only unconstrained types for two-dimensional arrays, requiring
-the user to supply appropriate bounds in object declarations. By providing
-constrained types or subtypes for these arrays, we simplify the code
-by eliminating the need to check for matching bounds. We do provide
-an unconstrained type (named \tyxffmxmono[]vector%
-\tyxffmxendmono[]) for one-dimensional arrays to use as the result
-type of the \tyxffmxmono[]row\tyxffmxendmono[] and %
-\tyxffmxmono[]col\tyxffmxendmono[] functions, which return partial
-rows and columns, respectively, and as the operand type of the %
-\tyxffmxmono[]*\tyxffmxendmono[] (inner-product) operator, which accepts
-partial rows and columns as operands. We do not use private types
-because we want the user to be able to exploit the fact that %
-\tyxffmxmono[]nxn\Symuns[]matrix\tyxffmxendmono[] is a two-dimensional
-array\EmDash[]for example, by using the normal subscript notation
-for references to a component of such an object. Also, were the auxiliary
-\tyxffmxmono[]row\tyxffmxendmono[] and \tyxffmxmono[]col%
-\tyxffmxendmono[] functions and the \tyxffmxmono[]*%
-\tyxffmxendmono[] operator meant to be used only by the %
-\tyxffmxmono[]solve\tyxffmxendmono[] function, they could have been
-defined in the body of \tyxffmxmono[]matrices\tyxffmxendmono[]; we
-define them, however, in its specification because they are likely
-to be of use elsewhere in the user\rsquo[]s application.%
-\Endpara[]
-\Para[]The body of \tyxffmxmono[]matrices\tyxffmxendmono[] is shown
-in Figure \Xref[\def\XrefName{body-of-matrices}].
-\FgBlock[\def\FgBlockPlace{H}]
-\Parbox[]
-\FgCap[\def\FgCapId{body-of-matrices}]Body of the \tyxffmxmono[]matrices%
-\tyxffmxendmono[] generic package\FgEndcap[]
-\Comp[]\tyxtstxbf[]package\tyxtstxendbf[] \tyxtstxbf[]body%
-\tyxtstxendbf[] matrices \tyxtstxbf[]is\tyxtstxendbf[]
-   \tyxtstxbf[]function\tyxtstxendbf[] row (row\Symuns[]index : positive;
-                 of\Symuns[]matrix : nxn\Symuns[]matrix;
-                 from      : positive;
-                 to        : natural) \tyxtstxbf[]return%
-\tyxtstxendbf[] vector \tyxtstxbf[]is\tyxtstxendbf[]
-      result : vector (from .. to);
-   \tyxtstxbf[]begin\tyxtstxendbf[]
-      \tyxtstxbf[]for\tyxtstxendbf[] i \tyxtstxbf[]in%
-\tyxtstxendbf[] from .. to \tyxtstxbf[]loop\tyxtstxendbf[]
-         result(i) := of\Symuns[]matrix(row\Symuns[]index,i);
-      \tyxtstxbf[]end\tyxtstxendbf[] \tyxtstxbf[]loop%
-\tyxtstxendbf[];
-      \tyxtstxbf[]return\tyxtstxendbf[] result;
-   \tyxtstxbf[]end\tyxtstxendbf[];
-   \tyxtstxbf[]function\tyxtstxendbf[] col (col\Symuns[]index : positive;
-                 of\Symuns[]matrix : nxn\Symuns[]matrix;
-                 from      : positive;
-                 to        : natural) \tyxtstxbf[]return%
-\tyxtstxendbf[] vector \tyxtstxbf[]is\tyxtstxendbf[]
-      result : vector (from .. to);
-   \tyxtstxbf[]begin\tyxtstxendbf[]
-      \tyxtstxbf[]for\tyxtstxendbf[] i \tyxtstxbf[]in%
-\tyxtstxendbf[] from .. to \tyxtstxbf[]loop\tyxtstxendbf[]
-         result(i) := of\Symuns[]matrix(i,col\Symuns[]index);
-      \tyxtstxbf[]end\tyxtstxendbf[] \tyxtstxbf[]loop%
-\tyxtstxendbf[];
-      \tyxtstxbf[]return\tyxtstxendbf[] result;
-   \tyxtstxbf[]end\tyxtstxendbf[];
-   \tyxtstxbf[]function\tyxtstxendbf[] \quot[]*\quot[] (left, right : vector) %
-\tyxtstxbf[]return\tyxtstxendbf[] float\Symuns[]type %
-\tyxtstxbf[]is\tyxtstxendbf[]
-      sum : float\Symuns[]type := 0.0;
-   \tyxtstxbf[]begin\tyxtstxendbf[]
-      \tyxtstxbf[]for\tyxtstxendbf[] i \tyxtstxbf[]in%
-\tyxtstxendbf[] left\rsquo[]range \tyxtstxbf[]loop%
-\tyxtstxendbf[]
-         sum := sum + left(i) * right(i);
-      \tyxtstxbf[]end\tyxtstxendbf[] \tyxtstxbf[]loop%
-\tyxtstxendbf[];
-      \tyxtstxbf[]return\tyxtstxendbf[] sum;
-   \tyxtstxbf[]end\tyxtstxendbf[];
-   \tyxtstxbf[]function\tyxtstxendbf[] solve (a : nxn\Symuns[]matrix;
-                   b : n\Symuns[]vector) \tyxtstxbf[]return%
-\tyxtstxendbf[] n\Symuns[]vector \tyxtstxbf[]is\tyxtstxendbf[] %
-\tyxtstxbf[]separate\tyxtstxendbf[];
-\tyxtstxbf[]end\tyxtstxendbf[];\Endcomp[]
-\EndParbox[]
-\FgEndblock[]
- The full bodies of the auxiliary functions are included, but that
-of \tyxffmxmono[]solve\tyxffmxendmono[], which is somewhat larger,
-is here represented merely by a body stub, and its proper body is
-presented in the next figure. The
-\TyPbrkNewp[]
- \tyxffmxmono[]row\tyxffmxendmono[] and \tyxffmxmono[]col%
-\tyxffmxendmono[] functions have been designed to return a partial
-row or column, extending from position \tyxffmxmono[]from%
-\tyxffmxendmono[] to position \tyxffmxmono[]to\tyxffmxendmono[]. (Note
-that \txtxemph[]null arrays\txtxendemph[]\EmDash[]arrays having no
-components\EmDash[]are allowed in Ada; \tyxffmxmono[]row%
-\tyxffmxendmono[] and \tyxffmxmono[]col\tyxffmxendmono[] return null
-vectors when \tyxffmxmono[]to\tyxffmxendmono[] \mthxsyxlt[] %
-\tyxffmxmono[]from\tyxffmxendmono[], as it does at several places
-in our realization of Doolittle\rsquo[]s method.) In the function
-implementing the \tyxffmxmono[]*\tyxffmxendmono[] (inner-product)
-operator for vectors, it is implicitly assumed, for simplicity of
-presentation, that the index ranges of the two operands, %
-\tyxffmxmono[]left\tyxffmxendmono[] and \tyxffmxmono[]right%
-\tyxffmxendmono[], are identical. The inner product of two null vectors
-is defined to be zero.\Endpara[]
-\Para[]The heart of Doolittle\rsquo[]s method is, of course, localized
-in the \tyxffmxmono[]solve\tyxffmxendmono[] function, whose proper
-body is shown in Figure \Xref[\def\XrefName{body-of-solve-normal}].
-\FgBlock[\def\FgBlockPlace{H}]
-\Parbox[]
-\FgCap[\def\FgCapId{body-of-solve-normal}]Proper body of the %
-\tyxffmxmono[]solve\tyxffmxendmono[] function, for normal matrices%
-\FgEndcap[]
-\Comp[]\tyxtstxbf[]separate\tyxtstxendbf[] (matrices)
-\tyxtstxbf[]function\tyxtstxendbf[] solve (a : nxn\Symuns[]matrix; b : n\Symuns[]vector) %
-\tyxtstxbf[]return\tyxtstxendbf[] n\Symuns[]vector \tyxtstxbf[]is%
-\tyxtstxendbf[]
-   x, y : n\Symuns[]vector;
-   lu   : nxn\Symuns[]matrix;
-   l    : nxn\Symuns[]matrix \tyxtstxbf[]renames\tyxtstxendbf[] lu;
-   u    : nxn\Symuns[]matrix \tyxtstxbf[]renames\tyxtstxendbf[] lu;
-\tyxtstxbf[]begin\tyxtstxendbf[]
-   -- Factorization step (compute l and u).
-   \tyxtstxbf[]for\tyxtstxendbf[] i \tyxtstxbf[]in%
-\tyxtstxendbf[] 1 .. n \tyxtstxbf[]loop\tyxtstxendbf[]
-      \tyxtstxbf[]for\tyxtstxendbf[] j \tyxtstxbf[]in%
-\tyxtstxendbf[] 1 .. i-1 \tyxtstxbf[]loop\tyxtstxendbf[]
-         l(i,j) :=
-            (a(i,j) - row(i,l,1,j-1) * col(j,u,1,j-1)) / u(j,j);
-      \tyxtstxbf[]end\tyxtstxendbf[] \tyxtstxbf[]loop%
-\tyxtstxendbf[];
-      \tyxtstxbf[]for\tyxtstxendbf[] j \tyxtstxbf[]in%
-\tyxtstxendbf[] 1 .. i \tyxtstxbf[]loop\tyxtstxendbf[]
-         u(j,i) := a(j,i) - row(j,l,1,j-1) * col(i,u,1,j-1);
-      \tyxtstxbf[]end\tyxtstxendbf[] \tyxtstxbf[]loop%
-\tyxtstxendbf[];
-   \tyxtstxbf[]end\tyxtstxendbf[] \tyxtstxbf[]loop%
-\tyxtstxendbf[];
-   -- Forward substitution step (compute y).
-   \tyxtstxbf[]for\tyxtstxendbf[] i \tyxtstxbf[]in%
-\tyxtstxendbf[] 1 .. n \tyxtstxbf[]loop\tyxtstxendbf[]
-      y(i) := b(i) - row(i,l,1,i-1) * y(1..i-1);
-   \tyxtstxbf[]end\tyxtstxendbf[] \tyxtstxbf[]loop%
-\tyxtstxendbf[];
-   -- Backward substitution step (compute x).
-   \tyxtstxbf[]for\tyxtstxendbf[] i \tyxtstxbf[]in%
-\tyxtstxendbf[] \tyxtstxbf[]reverse\tyxtstxendbf[] 1 .. n %
-\tyxtstxbf[]loop\tyxtstxendbf[]
-      x(i) := (y(i) - row(i,u,i+1,n) * x(i+1..n)) / u(i,i);
-   \tyxtstxbf[]end\tyxtstxendbf[] \tyxtstxbf[]loop%
-\tyxtstxendbf[];
-   -- Return the result.
-   \tyxtstxbf[]return\tyxtstxendbf[] x;
-\tyxtstxbf[]end\tyxtstxendbf[];\Endcomp[]
-\EndParbox[]
-\FgEndblock[]
- As usual, the \tyxffmxmono[]l\tyxffmxendmono[] and %
-\tyxffmxmono[]u\tyxffmxendmono[] matrices, which are lower and upper
-triangles in shape, share the storage of an order-\tyxffmxmono[]n%
-\tyxffmxendmono[] matrix, \tyxffmxmono[]lu\tyxffmxendmono[]. (The
-names \tyxffmxmono[]l\tyxffmxendmono[] and \tyxffmxmono[]u%
-\tyxffmxendmono[] are both made synonymous with \tyxffmxmono[]lu%
-\tyxffmxendmono[] and play only documentary roles in the algorithm.)
-The diagonal of \tyxffmxmono[]u\tyxffmxendmono[] is that of %
-\tyxffmxmono[]lu\tyxffmxendmono[]; the diagonal of %
-\tyxffmxmono[]l\tyxffmxendmono[], which is unit triangular, is all
-ones and is not stored. The triangles \tyxffmxmono[]l%
-\tyxffmxendmono[] and \tyxffmxmono[]u\tyxffmxendmono[] are computed
-in the factorization step of our version of Doolittle\rsquo[]s method
-by alternately filling increasingly higher rows of %
-\tyxffmxmono[]l\tyxffmxendmono[] and columns of \tyxffmxmono[]u%
-\tyxffmxendmono[]. Note how the use of a simple abstraction for partial
-rows and columns and a
-\TyPbrkNewp[]
- familiar notation for inner products result in a clear and concise
-expression of the algorithm. For simplicity of presentation, no test
-for singularity is provided, and no provision for the raising of a
-user-defined exception signaling singularity is made.\Endpara[]
-\Para[]It should be pointed out that the type \tyxffmxmono[]nxn\Symuns[]matrix%
-\tyxffmxendmono[] could have been defined as a one-dimensional array
-(with bounds \tyxffmxmono[]1\tyxinterwordxsp[]..%
-\tyxinterwordxsp[]n\tyxffmxendmono[]) whose components are of the
-type \tyxffmxmono[]n\Symuns[]vector\tyxffmxendmono[]. One would have
-to pick an interpretation for such a definition as either a vector
-of row vectors or a vector of column vectors. Assuming the former
-for purposes of illustration, a reference to the \tyxffmxmono[]i%
-\tyxffmxendmono[],\tyxffmxmono[]j\tyxffmxendmono[]-th component of
-\tyxffmxmono[]u\tyxffmxendmono[] would be written \tyxffmxmono[]u(i)(j)%
-\tyxffmxendmono[]. Such an interpretation would allow a reference
-to a whole row (but not a whole column) of an \tyxffmxmono[]nxn\Symuns[]matrix%
-\tyxffmxendmono[]. By the same token, a partial row (but not a partial
-column) could be denoted by combining subscripting and slicing. For
-example, the \tyxffmxmono[]i\tyxffmxendmono[]th row of %
-\tyxffmxmono[]u\tyxffmxendmono[] extending from position %
-\tyxffmxmono[]i+1\tyxffmxendmono[] to position \tyxffmxmono[]n%
-\tyxffmxendmono[], as needed in the backward substitution step, would
-be denoted by \tyxffmxmono[]u(i)(i+1..n)\tyxffmxendmono[]. Defining
-\tyxffmxmono[]nxn\Symuns[]matrix\tyxffmxendmono[] as a vector of %
-\tyxffmxmono[]n\Symuns[]vector\tyxffmxendmono[]s would allow one to
-dispose of either the \tyxffmxmono[]row\tyxffmxendmono[] function
-or the \tyxffmxmono[]col\tyxffmxendmono[] function, but not both.%
-\Endpara[]
-\DivEndiv[]
-\DivLiv[\def\DivLivId{crout-skyline}]\HdMinLiv[]Solution for Skyline
-Matrices\HdMinEndiv[]
-\Para[]The solution for ordinary matrices is now modified to exploit
-the special properties of skyline matrices. First, we replace the
-generic package \tyxffmxmono[]matrices\tyxffmxendmono[] with one called
-\tyxffmxmono[]skyline\Symuns[]matrices\tyxffmxendmono[], whose specification
-is shown in Figure \Xref[\def\XrefName{spec-of-skyline-matrices}].
-\FgBlock[\def\FgBlockPlace{H}]
-\Parbox[]
-\FgCap[\def\FgCapId{spec-of-skyline-matrices}]Specification of the
-\tyxffmxmono[]skyline\Symuns[]matrices\tyxffmxendmono[] generic package%
-\FgEndcap[]
-\Comp[]\tyxtstxbf[]generic\tyxtstxendbf[]
-   \tyxtstxbf[]type\tyxtstxendbf[] float\Symuns[]type %
-\tyxtstxbf[]is\tyxtstxendbf[] \tyxtstxbf[]digits\tyxtstxendbf[] \Symlt[]\Symgt[];
-   n : \tyxtstxbf[]in\tyxtstxendbf[] positive;
-\tyxtstxbf[]package\tyxtstxendbf[] skyline\Symuns[]matrices %
-\tyxtstxbf[]is\tyxtstxendbf[]
-   \tyxtstxbf[]type\tyxtstxendbf[]    vector   \tyxtstxbf[]is%
-\tyxtstxendbf[] \tyxtstxbf[]array\tyxtstxendbf[] (positive %
-\tyxtstxbf[]range\tyxtstxendbf[] \Symlt[]\Symgt[]) \tyxtstxbf[]of%
-\tyxtstxendbf[] float\Symuns[]type;
-   \tyxtstxbf[]subtype\tyxtstxendbf[] n\Symuns[]vector %
-\tyxtstxbf[]is\tyxtstxendbf[] vector (1 .. n);
-   \tyxtstxbf[]type\tyxtstxendbf[] bounded\Symuns[]vector (lo : positive; hi : natural) %
-\tyxtstxbf[]is\tyxtstxendbf[] \tyxtstxbf[]record\tyxtstxendbf[]
-      e : vector (lo .. hi);
-   \tyxtstxbf[]end\tyxtstxendbf[] \tyxtstxbf[]record%
-\tyxtstxendbf[];
-   \tyxtstxbf[]type\tyxtstxendbf[] vector\Symuns[]ptr         %
-\tyxtstxbf[]is\tyxtstxendbf[] \tyxtstxbf[]access\tyxtstxendbf[] bounded\Symuns[]vector;
-   \tyxtstxbf[]type\tyxtstxendbf[] vector\Symuns[]ptrs        %
-\tyxtstxbf[]is\tyxtstxendbf[] \tyxtstxbf[]array\tyxtstxendbf[] (1 .. n) %
-\tyxtstxbf[]of\tyxtstxendbf[] vector\Symuns[]ptr;
-   \tyxtstxbf[]type\tyxtstxendbf[] nxn\Symuns[]skyline\Symuns[]matrix %
-\tyxtstxbf[]is\tyxtstxendbf[] \tyxtstxbf[]record\tyxtstxendbf[]
-      lower, upper : vector\Symuns[]ptrs;
-   \tyxtstxbf[]end\tyxtstxendbf[] \tyxtstxbf[]record%
-\tyxtstxendbf[];
-   \tyxtstxbf[]function\tyxtstxendbf[] row (row\Symuns[]index : positive;
-                 of\Symuns[]cols   : vector\Symuns[]ptrs;
-                 from      : positive) \tyxtstxbf[]return%
-\tyxtstxendbf[] vector;
-   \tyxtstxbf[]function\tyxtstxendbf[] \quot[]*\quot[] (left, right : vector) %
-\tyxtstxbf[]return\tyxtstxendbf[] float\Symuns[]type;
-   \tyxtstxbf[]function\tyxtstxendbf[] solve (a : nxn\Symuns[]skyline\Symuns[]matrix;
-                   b : n\Symuns[]vector) \tyxtstxbf[]return%
-\tyxtstxendbf[] n\Symuns[]vector;
-\tyxtstxbf[]end\tyxtstxendbf[];\Endcomp[]
-\EndParbox[]
-\FgEndblock[]
- In place of the type \tyxffmxmono[]nxn\Symuns[]matrix%
-\tyxffmxendmono[], we now define a type \tyxffmxmono[]nxn\Symuns[]skyline\Symuns[]matrix%
-\tyxffmxendmono[], which is a record of two components, each an array
-of pointers: the component \tyxffmxmono[]lower\tyxffmxendmono[] is
-a vector of pointers to the rows of the lower triangle, while the
-component \tyxffmxmono[]upper\tyxffmxendmono[] is a vector of pointers
-to the columns of the upper triangle. Pointers are used, of course,
-to permit the rows and columns to be allocated dynamically with just
-the right \ldquo[]size\rdquo[] once that size is known (dynamically
-allocated storage is accessed through the pointer value obtained when
-it is allocated). Each row or column is represented by the type %
-\tyxffmxmono[]bounded\Symuns[]vector\tyxffmxendmono[], which is a
-discriminated record containing one component, \tyxffmxmono[]e%
-\tyxffmxendmono[], and two discriminants, \tyxffmxmono[]lo%
-\tyxffmxendmono[] and \tyxffmxmono[]hi\tyxffmxendmono[]. The component
-\tyxffmxmono[]e\tyxffmxendmono[] is an object of the unconstrained
-array type \tyxffmxmono[]vector\tyxffmxendmono[] (whose definition
-has not changed) constrained by the bounds \tyxffmxmono[]lo%
-\tyxffmxendmono[] and \tyxffmxmono[]hi\tyxffmxendmono[]\EmDash[]that
-is, by the values of the discriminants. Each object of the type %
-\tyxffmxmono[]bounded\Symuns[]vector\tyxffmxendmono[] is thus self-describing
-as far as the bounds of the contained vector \tyxffmxmono[]e%
-\tyxffmxendmono[] are concerned. The bounds are supplied at the time
-of allocation of the object and remain fixed throughout its lifetime.%
-\Endpara[]
-\Para[]A comparison of Figures \Xref[\def\XrefName{spec-of-skyline-matrices}]
-and \Xref[\def\XrefName{spec-of-matrices}] will reveal that we dropped
-the \tyxffmxmono[]col\tyxffmxendmono[] function and simplified the
-\tyxffmxmono[]row\tyxffmxendmono[] function somewhat (i.e., by changing
-its parameters). We no longer need the \tyxffmxmono[]col%
-\tyxffmxendmono[] function because all the columns we need to reference
-are in upper triangles and are therefore now just one-dimensional
-arrays instead of one-dimensional cross sections of two-dimensional
-arrays (to be utterly precise, we should say that they are records
-that contain one-dimensional arrays). References to partial columns
-are easily obtained by using the slicing notation on column vectors.
-Unfortunately, not all of the rows referenced in Doolittle\rsquo[]s
-method are rows of lower triangles; if they were, we could dispense
-with the \tyxffmxmono[]row\tyxffmxendmono[] function for similar reasons.
-The backward substitution step references a row of %
-\tyxffmxmono[]u\tyxffmxendmono[]. That row cuts across the column
-vectors representing the upper triangle of \tyxffmxmono[]lu%
-\tyxffmxendmono[], and it might even have some components lying outside
-the skyline envelope of \tyxffmxmono[]lu\tyxffmxendmono[]. Thus the
-\tyxffmxmono[]row\tyxffmxendmono[] function is retained for the sole
-purpose of extracting a row from an upper triangle, and it is particularized
-to that aim. The partial row needed in the backward substitution step
-always extends to the end of the row, so we no longer need to pass
-the row\rsquo[]s upper bound as a parameter. Furthermore, since %
-\tyxffmxmono[]row\tyxffmxendmono[] is asked to extract a row only
-from the upper triangle of a skyline matrix, we no longer pass an
-entire skyline matrix to it; we merely pass the desired upper triangle,
-represented by the vector of pointers to its columns.\Endpara[]
-\Para[]Turning now to the body of \tyxffmxmono[]skyline\Symuns[]matrices%
-\tyxffmxendmono[] (Figure \Xref[\def\XrefName{body-of-skyline-matrices}]),
-\FgBlock[]
-\Parbox[]
-\FgCap[\def\FgCapId{body-of-skyline-matrices}]Body of the %
-\tyxffmxmono[]skyline\Symuns[]matrices\tyxffmxendmono[] generic package%
-\FgEndcap[]
-\Comp[]\tyxtstxbf[]with\tyxtstxendbf[] min\Symuns[]and\Symuns[]max;
-\tyxtstxbf[]package\tyxtstxendbf[] \tyxtstxbf[]body%
-\tyxtstxendbf[] skyline\Symuns[]matrices \tyxtstxbf[]is%
-\tyxtstxendbf[]
-   \tyxtstxbf[]package\tyxtstxendbf[] natural\Symuns[]min\Symuns[]and\Symuns[]max %
-\tyxtstxbf[]is\tyxtstxendbf[] \tyxtstxbf[]new\tyxtstxendbf[] min\Symuns[]and\Symuns[]max (natural);
-   \tyxtstxbf[]use\tyxtstxendbf[]     natural\Symuns[]min\Symuns[]and\Symuns[]max;
-   \tyxtstxbf[]function\tyxtstxendbf[] row (row\Symuns[]index : positive;
-                 of\Symuns[]cols   : vector\Symuns[]ptrs;
-                 from      : positive) \tyxtstxbf[]return%
-\tyxtstxendbf[] vector \tyxtstxbf[]is\tyxtstxendbf[]
-      result : vector (from .. n);
-   \tyxtstxbf[]begin\tyxtstxendbf[]
-      \tyxtstxbf[]for\tyxtstxendbf[] i \tyxtstxbf[]in%
-\tyxtstxendbf[] from .. n \tyxtstxbf[]loop\tyxtstxendbf[]
-         \tyxtstxbf[]if\tyxtstxendbf[] row\Symuns[]index \Symgt[]= of\Symuns[]cols(i).lo %
-\tyxtstxbf[]then\tyxtstxendbf[]
-            result(i) := of\Symuns[]cols(i).e(row\Symuns[]index);
-         \tyxtstxbf[]else\tyxtstxendbf[]
-            result(i) := 0.0;
-         \tyxtstxbf[]end\tyxtstxendbf[] \tyxtstxbf[]if%
-\tyxtstxendbf[];
-      \tyxtstxbf[]end\tyxtstxendbf[] \tyxtstxbf[]loop%
-\tyxtstxendbf[];
-      \tyxtstxbf[]return\tyxtstxendbf[] result;
-   \tyxtstxbf[]end\tyxtstxendbf[];
-   \tyxtstxbf[]function\tyxtstxendbf[] \quot[]*\quot[] (left, right : vector) %
-\tyxtstxbf[]return\tyxtstxendbf[] float\Symuns[]type %
-\tyxtstxbf[]is\tyxtstxendbf[]
-      sum : float\Symuns[]type := 0.0;
-   \tyxtstxbf[]begin\tyxtstxendbf[]
-      \tyxtstxbf[]for\tyxtstxendbf[] i \tyxtstxbf[]in%
-\tyxtstxendbf[] max(left\rsquo[]first, right\rsquo[]first) ..
-               min(left\rsquo[]last,  right\rsquo[]last) %
-\tyxtstxbf[]loop\tyxtstxendbf[]
-         sum := sum + left(i) * right(i);
-      \tyxtstxbf[]end\tyxtstxendbf[] \tyxtstxbf[]loop%
-\tyxtstxendbf[];
-      \tyxtstxbf[]return\tyxtstxendbf[] sum;
-   \tyxtstxbf[]end\tyxtstxendbf[];
-   \tyxtstxbf[]function\tyxtstxendbf[] solve (a : nxn\Symuns[]skyline\Symuns[]matrix;
-                   b : n\Symuns[]vector) \tyxtstxbf[]return%
-\tyxtstxendbf[] n\Symuns[]vector \tyxtstxbf[]is\tyxtstxendbf[] %
-\tyxtstxbf[]separate\tyxtstxendbf[];
-\tyxtstxbf[]end\tyxtstxendbf[];\Endcomp[]
-\EndParbox[]
-\FgEndblock[]
- we note the following changes from its predecessor:
-\LstList[]
-\LstItem[]The body of the \tyxffmxmono[]row\tyxffmxendmono[] function
-now returns a row vector containing, in each position, either a component
-of the skyline matrix whose upper triangle is passed as an argument
-(if within the skyline envelope) or zero (if outside it). The bounds
-of the vector it returns could be shortened if zeros lie at either
-end, but that optimization hardly seems worthwhile.\LstEnditem[]
-\LstItem[]The \tyxffmxmono[]*\tyxffmxendmono[] operator (inner-product
-function) can now receive a pair of vectors of different lengths;
-because the missing components are zero, they do not contribute to
-the inner product, and the loop can extend from the greater of the
-lower bounds of the two vectors to the lesser of their upper bounds.%
-\LstEnditem[]
-\LstEndlist[]
-\Endpara[]
-\Para[]The revised proper body of the \tyxffmxmono[]solve%
-\tyxffmxendmono[] function is shown in Figure \Xref[\def\XrefName{body-of-solve-skyline}].
-\FgBlock[]
-\Parbox[]
-\FgCap[\def\FgCapId{body-of-solve-skyline}]Proper body of the %
-\tyxffmxmono[]solve\tyxffmxendmono[] function, for skyline matrices%
-\FgEndcap[]
-\Comp[]\tyxtstxbf[]with\tyxtstxendbf[] unchecked\Symuns[]deallocation;
-\tyxtstxbf[]separate\tyxtstxendbf[] (skyline\Symuns[]matrices)
-\tyxtstxbf[]function\tyxtstxendbf[] solve (a : nxn\Symuns[]skyline\Symuns[]matrix;
-                b : n\Symuns[]vector) \tyxtstxbf[]return%
-\tyxtstxendbf[] n\Symuns[]vector \tyxtstxbf[]is\tyxtstxendbf[]
-   x, y : n\Symuns[]vector;
-   lu   : nxn\Symuns[]skyline\Symuns[]matrix;
-   l    : vector\Symuns[]ptrs \tyxtstxbf[]renames\tyxtstxendbf[] lu.lower;
-   u    : vector\Symuns[]ptrs \tyxtstxbf[]renames\tyxtstxendbf[] lu.upper;
-   \tyxtstxbf[]procedure\tyxtstxendbf[] free \tyxtstxbf[]is%
-\tyxtstxendbf[]
-      \tyxtstxbf[]new\tyxtstxendbf[] unchecked\Symuns[]deallocation (bounded\Symuns[]vector, vector\Symuns[]ptr);
-\tyxtstxbf[]begin\tyxtstxendbf[]
-   -- Allocate the rows and columns of lu with the shape of a.
-   \tyxtstxbf[]for\tyxtstxendbf[] i \tyxtstxbf[]in%
-\tyxtstxendbf[] 1 .. n \tyxtstxbf[]loop\tyxtstxendbf[]
-      l(i) := \tyxtstxbf[]new\tyxtstxendbf[] bounded\Symuns[]vector (lo =\Symgt[] a.lower(i).lo, hi =\Symgt[] i-1);
-      u(i) := \tyxtstxbf[]new\tyxtstxendbf[] bounded\Symuns[]vector (lo =\Symgt[] a.upper(i).lo, hi =\Symgt[] i);
-   \tyxtstxbf[]end\tyxtstxendbf[] \tyxtstxbf[]loop%
-\tyxtstxendbf[];
-   -- Factorization step (compute l and u).
-   \tyxtstxbf[]for\tyxtstxendbf[] i \tyxtstxbf[]in%
-\tyxtstxendbf[] 1 .. n \tyxtstxbf[]loop\tyxtstxendbf[]
-      \tyxtstxbf[]for\tyxtstxendbf[] j \tyxtstxbf[]in%
-\tyxtstxendbf[] l(i).lo .. i-1 \tyxtstxbf[]loop\tyxtstxendbf[]
-         l(i).e(j) := (a.lower(i).e(j) -
-            l(i).e(l(i).lo..j-1) * u(j).e(u(j).lo..j-1)) / u(j).e(j);
-      \tyxtstxbf[]end\tyxtstxendbf[] \tyxtstxbf[]loop%
-\tyxtstxendbf[];
-      \tyxtstxbf[]for\tyxtstxendbf[] j \tyxtstxbf[]in%
-\tyxtstxendbf[] u(i).lo .. i \tyxtstxbf[]loop\tyxtstxendbf[]
-         u(i).e(j) := a.upper(i).e(j) -
-            l(j).e(l(j).lo..j-1) * u(i).e(u(i).lo..j-1);
-      \tyxtstxbf[]end\tyxtstxendbf[] \tyxtstxbf[]loop%
-\tyxtstxendbf[];
-   \tyxtstxbf[]end\tyxtstxendbf[] \tyxtstxbf[]loop%
-\tyxtstxendbf[];
-   -- Forward substitution step (compute y).
-   \tyxtstxbf[]for\tyxtstxendbf[] i \tyxtstxbf[]in%
-\tyxtstxendbf[] 1 .. n \tyxtstxbf[]loop\tyxtstxendbf[]
-      y(i) := b(i) - l(i).e(l(i).lo..i-1) * y(1..i-1);
-   \tyxtstxbf[]end\tyxtstxendbf[] \tyxtstxbf[]loop%
-\tyxtstxendbf[];
-   -- Backward substitution step (compute x).
-   \tyxtstxbf[]for\tyxtstxendbf[] i \tyxtstxbf[]in%
-\tyxtstxendbf[] \tyxtstxbf[]reverse\tyxtstxendbf[] 1 .. n %
-\tyxtstxbf[]loop\tyxtstxendbf[]
-      x(i) := (y(i) - row(i,u,i+1) * x(i+1..n)) / u(i).e(i);
-   \tyxtstxbf[]end\tyxtstxendbf[] \tyxtstxbf[]loop%
-\tyxtstxendbf[];
-   -- Deallocate the rows and columns of lu.
-   \tyxtstxbf[]for\tyxtstxendbf[] i \tyxtstxbf[]in%
-\tyxtstxendbf[] 1 .. n \tyxtstxbf[]loop\tyxtstxendbf[]
-      free (l(i));
-      free (u(i));
-   \tyxtstxbf[]end\tyxtstxendbf[] \tyxtstxbf[]loop%
-\tyxtstxendbf[];
-   -- Return the result.
-   \tyxtstxbf[]return\tyxtstxendbf[] x;
-\tyxtstxbf[]end\tyxtstxendbf[];\Endcomp[]
-\EndParbox[]
-\FgEndblock[]
- One small change is that \tyxffmxmono[]l\tyxffmxendmono[] and %
-\tyxffmxmono[]u\tyxffmxendmono[] are now made synonymous with the
-lower and upper triangular components of \tyxffmxmono[]lu%
-\tyxffmxendmono[], respectively, rather than with the entire object
-\tyxffmxmono[]lu\tyxffmxendmono[], as was done before. This simplifies
-the expressions we are required to write to denote components, rows,
-or columns of \tyxffmxmono[]lu\tyxffmxendmono[] (e.g., we write %
-\tyxffmxmono[]l(i).e(j)\tyxffmxendmono[] to denote the %
-\tyxffmxmono[]i\tyxffmxendmono[],\tyxffmxmono[]j%
-\tyxffmxendmono[]-th component of the lower triangle of %
-\tyxffmxmono[]lu\tyxffmxendmono[]). Similar renaming declarations
-could be given for the lower and upper triangles of %
-\tyxffmxmono[]a\tyxffmxendmono[], but there are few references to
-\tyxffmxmono[]a\tyxffmxendmono[] in \tyxffmxmono[]solve%
-\tyxffmxendmono[], so the savings would not be significant. The %
-\tyxffmxmono[]solve\tyxffmxendmono[] function includes two steps not
-previously required: one to allocate the rows and columns of the local
-\tyxffmxmono[]lu\tyxffmxendmono[] skyline matrix before filling them
-in the factorization step, and one to deallocate them just before
-returning the result. It is a consequence of Doolittle\rsquo[]s method
-that the skyline envelope of \tyxffmxmono[]lu\tyxffmxendmono[] is
-the same as that of \tyxffmxmono[]a\tyxffmxendmono[]. Thus, we allocate
-the \tyxffmxmono[]i\tyxffmxendmono[]th row of \tyxffmxmono[]lu%
-\tyxffmxendmono[] to have the same lower bound as the %
-\tyxffmxmono[]i\tyxffmxendmono[]th row of \tyxffmxmono[]a%
-\tyxffmxendmono[] and an upper bound of \tyxffmxmono[]i-1%
-\tyxffmxendmono[] (recall that the lower triangle stops just short
-of the diagonal); similarly, we allocate the \tyxffmxmono[]i%
-\tyxffmxendmono[]th column of \tyxffmxmono[]lu\tyxffmxendmono[] to
-have the same lower bound as the \tyxffmxmono[]i%
-\tyxffmxendmono[]th column of \tyxffmxmono[]a\tyxffmxendmono[] and
-an upper bound of \tyxffmxmono[]i\tyxffmxendmono[] (the upper triangle
-includes the diagonal).\Endpara[]
-\Para[]In the factorization step, we see that the two inner loops
-now start at the index of the first nonzero component of the row or
-column being filled, instead of at 1, since preceding components (those
-outside the skyline envelope) do not exist. The backward substitution
-step contains the only remaining reference to the \tyxffmxmono[]row%
-\tyxffmxendmono[] function.\Endpara[]
-\Para[]Our solution for skyline matrices obviously saves space by
-not storing zeros outside the envelope of a skyline matrix. It also
-saves time by not computing them. Surprisingly, it is more efficient
-than the solution for normal matrices in yet another way: it calls
-far fewer subprograms to obtain (partial) rows or columns, and in
-so doing copies much less data.\Endpara[]
-\Para[]In view of the similarities between the two solutions, it is
-reasonable to ask whether one can write a single version of %
-\tyxffmxmono[]solve\tyxffmxendmono[] that is suitable either for normal
-matrices or for skyline matrices. The answer is yes, but we only sketch
-the details here. One starts by separating the \tyxffmxmono[]solve%
-\tyxffmxendmono[] function from the rest of the matrix abstraction,
-leaving a generic library package called \tyxffmxmono[]matrices%
-\tyxffmxendmono[] and a generic library function called %
-\tyxffmxmono[]solve\tyxffmxendmono[]. The matrix type would be exported
-from \tyxffmxmono[]matrices\tyxffmxendmono[] and imported into %
-\tyxffmxmono[]solve\tyxffmxendmono[]; the two different implementations
-of the matrix type would be provided by two different realizations
-of \tyxffmxmono[]matrices\tyxffmxendmono[]. To gain the desired degree
-of reusability, the single version of \tyxffmxmono[]solve%
-\tyxffmxendmono[] would have to be written so that it makes no assumptions
-about the implementation of the matrix type that it imports. Thus,
-the generic formal type by which it imports the matrix type would
-have to be a private type. Subscript and slice notation could then
-no longer be used in \tyxffmxmono[]solve\tyxffmxendmono[] to denote
-components, rows, or columns of matrices; hence these operations would
-have to be exported (in the form of subprograms) by %
-\tyxffmxmono[]matrices\tyxffmxendmono[], and imported by %
-\tyxffmxmono[]solve\tyxffmxendmono[].\NtFoot[]\NtNtpar[]In addition
-to a function for fetching a component of a matrix, given the matrix
-and its component indices, a procedure for storing into a component
-of a matrix\EmDash[]given the matrix, its component indices, and the
-value to be stored\EmDash[]would have to be provided by the matrix
-abstraction.\NtEndntpar[]\NtEndfoot[] If the rest of the client\rsquo[]s
-application (exclusive of \tyxffmxmono[]solve\tyxffmxendmono[]) is
-also to be independent of the matrix type, then it, too, would have
-to use the abstract operations exported from \tyxffmxmono[]matrices%
-\tyxffmxendmono[]. The abstraction could \txtxemph[]force%
-\txtxendemph[] the client to be independent of the details of the
-matrix type by defining that type as a private type. Clearly, the
-benefits of reusability come at some cost\EmDash[]the substitution
-of explicit operations (and their incurred overheads) for predefined
-operations.\Endpara[]
-\Para[]But there is another cost as well. In the factorization step
-of the skyline adaptation of \tyxffmxmono[]solve%
-\tyxffmxendmono[], we skipped over the computation of components of
-\tyxffmxmono[]l\tyxffmxendmono[] and \tyxffmxmono[]u%
-\tyxffmxendmono[] lying outside the skyline envelope, thus saving
-time as well as space. In the \ldquo[]generalized\rdquo[] version
-being contemplated here, we cannot know in advance whether a component
-lies outside the envelope, so we must compute it, even if it turns
-out to be zero. In order to retain the storage savings represented
-by not storing zeros outside the skyline envelope, the procedure (exported
-by \tyxffmxmono[]matrices\tyxffmxendmono[]) that stores a value into
-a component of a matrix would be given, in the skyline case, the responsibility
-for allocating a row (if the component being set is in the lower triangle)
-or a column (if it is in the upper triangle) upon the first attempt
-to store a nonzero value into a particular component; it would just
-discard zeros destined for a row or column that it has not yet allocated.
-(Note that pointers are initialized to \tyxffmxmono[]%
-\tyxtstxbf[]null\tyxtstxendbf[]\tyxffmxendmono[] in Ada, making it
-easy to detect that a row or column has never been allocated.) This
-responsibility of the component-storing procedure meshes well with
-our realization of Doolittle\rsquo[]s method, since the components
-of the rows and columns of \tyxffmxmono[]lu\tyxffmxendmono[] are set
-in increasing order\EmDash[]that is, it is \txtxemph[]possible%
-\txtxendemph[] to defer allocating a row or column of %
-\tyxffmxmono[]lu\tyxffmxendmono[] until an attempt is made to store
-its first nonzero component. In conjunction with this, the %
-\tyxffmxmono[]row\tyxffmxendmono[] and \tyxffmxmono[]col%
-\tyxffmxendmono[] functions must be prepared to return null arrays
-if their arguments denote rows or columns that have not yet been allocated.
-Although the responsibility for allocating rows and columns can be
-built into the skyline version of the component-storing procedure
-that would be exported with the matrix type, there is no way to handle
-the \ldquo[]automatic\rdquo[] deallocation of the rows and columns
-of a matrix (in the skyline case) upon leaving the scope of the object
-declaration for the matrix. Of course, Ada allows for such dynamically
-allocated storage to be reclaimed automatically (in this case, when
-\tyxffmxmono[]solve\tyxffmxendmono[] returns); but as we said earlier
-in this chapter, such garbage collection is not routinely implemented
-in Ada.\NtFoot[]\NtNtpar[]Ada 9X will likely introduce \ldquo[]finalization\rdquo[]
-of objects or types, which will solve this problem elegantly.%
-\NtEndntpar[]\NtEndfoot[] If explicit deallocation is desired, a procedure
-to deallocate a matrix could be exported with the type, imported by
-\tyxffmxmono[]solve\tyxffmxendmono[], and called by %
-\tyxffmxmono[]solve\tyxffmxendmono[] just before it returns. In the
-case of normal matrices, the deallocation procedure would do nothing,
-while for skyline matrices it would have the behavior shown in Figure
-\Xref[\def\XrefName{body-of-solve-skyline}].\Endpara[]
-\Para[]The expense of computing and then discarding zeros outside
-the skyline envelope can, actually, be saved if we are willing to
-export additional operations with the matrix type, as part of the
-matrix abstraction. That is, we could export a pair of functions that
-give the lower bound of a row or a column of a matrix. They would
-be used in the factorization step to skip over components of %
-\tyxffmxmono[]l\tyxffmxendmono[] and \tyxffmxmono[]u%
-\tyxffmxendmono[] outside the skyline envelope (in the skyline case).
-The rows and columns of \tyxffmxmono[]l\tyxffmxendmono[] and %
-\tyxffmxmono[]u\tyxffmxendmono[] would still be allocated by the component-storing
-procedure discussed above. Thus, in the factorization step, we would
-not ask for the lower bounds of the rows and columns of %
-\tyxffmxmono[]lu\tyxffmxendmono[] (since they will not have been allocated
-yet); rather, we would ask for the lower bounds of the rows and columns
-of \tyxffmxmono[]a\tyxffmxendmono[]. In the case of normal matrices,
-these enquiry functions would be designed so that they always return
-1, of course. Clearly, such functions are not very elegant as part
-of a reusable abstraction, but they do allow us to retain some of
-the speed economies in the skyline case.\Endpara[]
-\Para[]Finally, the matrix type should really be declared %
-\tyxffmxmono[]\tyxtstxbf[]limited\tyxtstxendbf[]%
-\tyxffmxendmono[] \tyxffmxmono[]\tyxtstxbf[]private%
-\tyxtstxendbf[]\tyxffmxendmono[], and not just \tyxffmxmono[]%
-\tyxtstxbf[]private\tyxtstxendbf[]\tyxffmxendmono[], in %
-\tyxffmxmono[]matrices\tyxffmxendmono[]. The assignment operation
-and the predefined equality comparison operation, which %
-\txtxemph[]are\txtxendemph[] among the few operations implicitly declared
-for private types, are \txtxemph[]not\txtxendemph[] implicitly declared
-for limited types, and that can be important to us. When pointers
-are used in the implementation of an abstraction, one needs to determine
-whether assignment and equality comparison make sense. In our case,
-they do not. Assignment of one skyline matrix to another would copy
-only the contained pointer values; it would not replicate the rows
-and columns of the source value. Because the rows and columns of the
-target would therefore be the same as those of the source, after the
-assignment, changes to one would affect the other. By the same token,
-two skyline matrices with different, but equal, rows and columns would
-not compare equal, because the predefined operation for equality comparison
-would compare only the pointer values. Sharing of storage is desired
-in some applications, but not here. In a reusable abstraction, it
-is important to suppress the implicit declaration of operations that
-do not make sense, so that the abstraction will not be misused. Declaring
-the matrix type in \tyxffmxmono[]matrices\tyxffmxendmono[] as %
-\tyxffmxmono[]\tyxtstxbf[]limited\tyxtstxendbf[]%
-\tyxffmxendmono[] \tyxffmxmono[]\tyxtstxbf[]private%
-\tyxtstxendbf[]\tyxffmxendmono[] will accomplish that. (We were not
-concerned in Section \Xref[\def\XrefName{crout-skyline}] with the
-risks of \txtxemph[]not\txtxendemph[] making the matrix type limited
-because, as we said there, we specifically wanted the user to be able
-to exploit knowledge of its implementation, which required us to forgo
-the use of private types and therefore also limited types; we tacitly
-assumed that the user would not misuse that knowledge by, for example,
-assigning or comparing skyline matrices.) Although assignment and
-equality comparison of matrices are not needed in \tyxffmxmono[]solve%
-\tyxffmxendmono[], no such assumption should be made by the designer
-of \tyxffmxmono[]matrices\tyxffmxendmono[], if its two versions are
-truly meant to be reused in a variety of applications. Thus, the designer
-of \tyxffmxmono[]matrices\tyxffmxendmono[] would be compelled to provide
-those operations explicitly as part of the matrix abstraction, using
-subprograms or operator overloading; of course, the designer of %
-\tyxffmxmono[]matrices\tyxffmxendmono[] could then also ensure that
-the operations have the desired behavior in the skyline case. These
-considerations dictate that the generic formal type by which %
-\tyxffmxmono[]solve\tyxffmxendmono[] imports the matrix type must
-also be declared \tyxffmxmono[]\tyxtstxbf[]limited%
-\tyxtstxendbf[]\tyxffmxendmono[] \tyxffmxmono[]\tyxtstxbf[]private%
-\tyxtstxendbf[]\tyxffmxendmono[], but that is possible precisely because
-\tyxffmxmono[]solve\tyxffmxendmono[] does not need assignment or the
-predefined equality comparison operation for the matrix type.%
-\Endpara[]
-\DivEndiv[]
-\DivEndiii[]
-\DivLiii[]\HdMjLiii[\def\HdMjLiiiFntGenlTsz{H}\def\HdMjLiiiNumPostpunc{}\def\HdMjLiiiNumFirstdisp{99}]Acknowledgments%
-\HdMjEndiii[]
-\Para[]The preparation of this chapter was supported by the Strategic
-Defense Initiative Organization, Office of the U. S. Secretary of
-Defense, under PMA E2304.\Endpara[]
-\DivEndiii[]
-\Bib[\BibHdPosPostvskp=7pt plus3pt minus1pt \BibHdPosPrevskp=20pt plus7pt minus4pt \def\BibHdFntTsz{H}\BibHspaceWAmt=26pt ]%
-\Bibdat[]global\BibEnddat[]\Endbib[]
-\DivEndii[]
-\DivEndbod[]
-\Enddoc[]
-
diff --git a/spectral/salishan/doctors/sisal/doctors.if1 b/spectral/salishan/doctors/sisal/doctors.if1
deleted file mode 100644 (file)
index d8e56ea..0000000
+++ /dev/null
@@ -1,316 +0,0 @@
-T 1 1 0    %na=Boolean
-T 2 1 1    %na=Character
-T 3 1 2    %na=Double
-T 4 1 3    %na=Integer
-T 5 1 4    %na=Null
-T 6 1 5    %na=Real
-T 7 1 6    %na=WildBasic
-T 8 10
-T 9 0  4    %na=queue
-T 10 0 9    %na=queue2
-T 11 8 4       0
-T 12 8 6       0
-T 13 3 11      12
-T 14 3 11      11
-T 15 8 9       0
-T 16 8 4       15
-T 17 8 9       15
-T 18 3 16      17
-T 19 8 10      15
-T 20 8 9       19
-T 21 3 17      20
-T 22 8 10      0
-T 23 8 4       22
-T 24 8 10      17
-T 25 3 23      24
-T 26 6 9
-T 27 8 26      0
-T 28 8 26      27
-T 29 3 17      28
-T 30 4 9
-C$  C Faked IF1CHECK
-C$  D Nodes are DFOrdered
-C$  F Livermore Frontend   Version1.8
-I      13      "random"        %sl=22
-I      14      "next_seed"     %sl=23
-G      18      "well_persons"  %sl=30
-E      12 1    0 1     9       %mk=V
-E      12 2    0 2     9       %mk=V
-N 1    120     %sl=34
-L              1 1     13 "random"     %mk=V
-E      0 1     1 2     4        %na=seed       %mk=V   %sl=34
-N 2    116     %sl=35
-E      0 2     2 1     9        %na=patients   %mk=V   %sl=35
-N 3    124     %sl=38
-E      1 1     3 1     6        %na=x  %mk=V   %sl=38
-L              3 2     6 "0.7" %mk=V
-N 4    151     %sl=36
-E      2 1     4 1     4        %na=size       %mk=V   %sl=36
-N 5    124     %sl=38
-E      2 1     5 1     4        %na=size       %mk=V   %sl=38
-L              5 2     4 "0"   %mk=V
-N 6    152     %sl=36
-E      4 1     6 1     6       %mk=V
-E      1 1     6 2     6        %na=x  %mk=V   %sl=36
-N 7    141     %sl=38
-E      5 1     7 1     1       %mk=V
-E      3 1     7 2     1       %mk=V
-N 8    122     %sl=36
-E      6 1     8 1     6       %mk=V
-L              8 2     6 "0.7" %mk=V
-N 9    128     %sl=36
-E      8 1     9 1     6       %mk=V
-N 10   141     %sl=36
-E      9 1     10 1    4       %mk=V
-L              10 2    4 "1"   %mk=V
-N 11   129
-E      7 1     11 1    1       %mk=V
-{ Compound  12   1
-G      0
-E      0 1     0 1     4       %mk=V
-G      0       %sl=40
-E      5 1     0 1     9       %mk=V
-E      4 1     0 2     9       %mk=V
-N 1    105     %sl=41
-E      0 2     1 1     9        %na=patients   %mk=V   %sl=41
-E      0 4     1 2     4        %na=size       %mk=V   %sl=41
-N 2    105     %sl=42
-E      0 2     2 1     9        %na=patients   %mk=V   %sl=42
-E      0 3     2 2     4        %na=sick       %mk=V   %sl=42
-N 3    113     %sl=41
-E      0 2     3 1     9        %na=patients   %mk=V   %sl=41
-E      0 3     3 2     4        %na=sick       %mk=V   %sl=41
-E      1 1     3 3     4       %mk=V
-N 4    103     %sl=42
-L              4 1     4 "1"   %mk=V
-E      2 1     4 2     4       %mk=V
-N 5    111     %sl=41
-E      3 1     5 1     9       %mk=V
-G      0       %sl=39
-E      0 2     0 1     9        %na=patients   %mk=V   %sl=39
-E      1 1     0 2     9       %mk=V
-N 1    103     %sl=39
-L              1 1     4 "1"   %mk=V
-} 12 1 3 0 1 2 %sl=39
-E      11 1    12 1    4       %mk=V
-E      0 2     12 2    9        %na=patients   %mk=V   %sl=39
-E      10 1    12 3    4        %na=sick       %mk=V   %sl=41
-E      2 1     12 4    4        %na=size       %mk=V   %sl=41
-G      21      "nurse" %sl=56
-E      7 1     0 1     9       %mk=V
-E      7 2     0 2     10      %mk=V
-E      7 3     0 3     9       %mk=V
-N 1    116     %sl=60
-E      0 1     1 1     9        %na=patients   %mk=V   %sl=60
-N 2    116     %sl=61
-E      0 2     2 1     9        %na=doctors    %mk=V   %sl=61
-N 3    124     %sl=63
-E      1 1     3 1     4        %na=n_patients %mk=V   %sl=63
-L              3 2     4 "0"   %mk=V
-N 4    124     %sl=63
-E      2 1     4 1     4        %na=n_doctors  %mk=V   %sl=63
-L              4 2     4 "0"   %mk=V
-N 5    141     %sl=63
-E      3 1     5 1     1       %mk=V
-E      4 1     5 2     1       %mk=V
-N 6    129
-E      5 1     6 1     1       %mk=V
-{ Compound   7   1
-G      0
-E      0 1     0 1     4       %mk=V
-G      0       %sl=65
-E      5 1     0 1     9       %mk=V
-E      8 1     0 2     10      %mk=V
-E      7 1     0 3     9       %mk=V
-N 1    112     %sl=66
-E      0 2     1 1     9        %na=patients   %mk=V   %sl=66
-N 2    105     %sl=67
-E      0 2     2 1     9        %na=patients   %mk=V   %sl=67
-L              2 2     4 "1"   %mk=V
-N 3    105     %sl=67
-E      0 3     3 1     9        %na=doctors    %mk=V   %sl=67
-L              3 2     4 "1"   %mk=V
-N 4    112     %sl=68
-E      0 3     4 1     9        %na=doctors    %mk=V   %sl=68
-N 5    115     %sl=66
-E      1 1     5 1     9       %mk=V
-L              5 2     4 "1"   %mk=V
-N 6    103     %sl=67
-L              6 1     4 "1"   %mk=V
-E      2 1     6 2     4       %mk=V
-E      3 1     6 3     4       %mk=V
-N 7    115     %sl=68
-E      4 1     7 1     9       %mk=V
-L              7 2     4 "1"   %mk=V
-N 8    103     %sl=67
-L              8 1     4 "1"   %mk=V
-E      6 1     8 2     9       %mk=V
-G      0       %sl=64
-E      0 2     0 1     9        %na=patients   %mk=V   %sl=64
-E      1 1     0 2     10      %mk=V
-E      0 3     0 3     9        %na=doctors    %mk=V   %sl=64
-N 1    103     %sl=64
-L              1 1     4 "1"   %mk=V
-} 7 1 3 0 1 2  %sl=64
-E      6 1     7 1     4       %mk=V
-E      0 1     7 2     9        %na=patients   %mk=V   %sl=64
-E      0 2     7 3     9        %na=doctors    %mk=V   %sl=64
-G      25      "examinations"  %sl=80
-E      13 1    0 1     10      %mk=V
-E      13 2    0 2     9       %mk=V
-E      13 3    0 3     9       %mk=V
-N 1    120     %sl=84
-L              1 1     13 "random"     %mk=V
-E      0 1     1 2     4        %na=seed       %mk=V   %sl=84
-N 2    109     %sl=85
-E      0 2     2 1     10       %na=in_exam    %mk=V   %sl=85
-N 3    131     %sl=88
-E      1 1     3 1     6        %na=x  %mk=V   %sl=88
-L              3 2     6 "0.3" %mk=V
-N 4    151     %sl=86
-E      2 1     4 1     4        %na=size       %mk=V   %sl=86
-N 5    124     %sl=88
-E      2 1     5 1     4        %na=size       %mk=V   %sl=88
-L              5 2     4 "0"   %mk=V
-N 6    139     %sl=88
-E      3 1     6 1     1       %mk=V
-N 7    152     %sl=86
-E      4 1     7 1     6       %mk=V
-E      1 1     7 2     6        %na=x  %mk=V   %sl=86
-N 8    141     %sl=88
-E      5 1     8 1     1       %mk=V
-E      6 1     8 2     1       %mk=V
-N 9    122     %sl=86
-E      7 1     9 1     6       %mk=V
-L              9 2     6 "0.3" %mk=V
-N 10   128     %sl=86
-E      9 1     10 1    6       %mk=V
-N 11   141     %sl=86
-E      10 1    11 1    4       %mk=V
-L              11 2    4 "1"   %mk=V
-N 12   129
-E      8 1     12 1    1       %mk=V
-{ Compound  13   1
-G      0
-E      0 1     0 1     4       %mk=V
-G      0       %sl=90
-E      9 1     0 1     10      %mk=V
-E      7 1     0 2     9       %mk=V
-E      8 1     0 3     9       %mk=V
-N 1    105     %sl=91
-E      0 2     1 1     10       %na=in_exam    %mk=V   %sl=91
-E      0 4     1 2     4        %na=size       %mk=V   %sl=91
-N 2    105
-E      0 2     2 1     10       %na=in_exam    %mk=V   %sl=92
-E      0 3     2 2     4        %na=cured      %mk=V   %sl=92
-N 3    105     %sl=92
-E      2 1     3 1     9       %mk=V
-L              3 2     4 "1"   %mk=V
-N 4    105
-E      0 2     4 1     10       %na=in_exam    %mk=V   %sl=93
-E      0 3     4 2     4        %na=cured      %mk=V   %sl=93
-N 5    105     %sl=93
-E      4 1     5 1     9       %mk=V
-L              5 2     4 "2"   %mk=V
-N 6    113     %sl=91
-E      0 2     6 1     10       %na=in_exam    %mk=V   %sl=91
-E      0 3     6 2     4        %na=cured      %mk=V   %sl=91
-E      1 1     6 3     9       %mk=V
-N 7    103     %sl=92
-L              7 1     4 "1"   %mk=V
-E      3 1     7 2     4       %mk=V
-N 8    103     %sl=93
-L              8 1     4 "1"   %mk=V
-E      5 1     8 2     4       %mk=V
-N 9    111     %sl=91
-E      6 1     9 1     10      %mk=V
-G      0       %sl=89
-E      0 2     0 1     10       %na=in_exam    %mk=V   %sl=89
-E      1 1     0 2     9       %mk=V
-E      2 1     0 3     9       %mk=V
-N 1    103     %sl=89
-L              1 1     4 "1"   %mk=V
-N 2    103     %sl=89
-L              2 1     4 "1"   %mk=V
-} 13 1 3 0 1 2 %sl=89
-E      12 1    13 1    4       %mk=V
-E      0 2     13 2    10       %na=in_exam    %mk=V   %sl=89
-E      11 1    13 3    4        %na=cured      %mk=V   %sl=91
-E      2 1     13 4    4        %na=size       %mk=V   %sl=91
-X      29      "doctors_office"        %sl=99
-E      1 1     0 1     26      %mk=V
-E      1 2     0 2     26      %mk=V
-{ Compound   1   4
-G      0       %sl=102
-L              0 3     4 "0"    %na=seed       %mk=V   %sl=103
-E      4 1     0 4     9        %na=doctor_out %mk=V   %sl=109
-E      0 2     0 5     9        %na=still_available    %mk=V   %sl=108
-E      5 1     0 6     10       %na=still_examining    %mk=V   %sl=110
-E      3 1     0 7     9        %na=patient_in %mk=V   %sl=107
-E      2 1     0 8     9        %na=still_sick %mk=V   %sl=106
-E      0 1     0 9     9        %na=still_well %mk=V   %sl=104
-E      6 1     0 10    10       %na=patient_doctor     %mk=V   %sl=111
-E      1 1     0 11    9        %na=patient_out        %mk=V   %sl=105
-N 1    103     %sl=105
-L              1 1     4 "1"   %mk=V
-N 2    103     %sl=106
-L              2 1     4 "1"   %mk=V
-N 3    103     %sl=107
-L              3 1     4 "1"   %mk=V
-N 4    103     %sl=109
-L              4 1     4 "1"   %mk=V
-N 5    103     %sl=110
-L              5 1     4 "1"   %mk=V
-N 6    103     %sl=111
-L              6 1     4 "1"   %mk=V
-G      0       %sl=112
-L              0 1     1 "true"        %mk=V
-G      0       %sl=113
-E      1 1     0 3     4        %na=seed       %mk=V   %sl=120
-E      8 3     0 4     9        %na=doctor_out %mk=V   %sl=118
-E      7 3     0 5     9        %na=still_available    %mk=V   %sl=118
-E      8 1     0 6     10       %na=still_examining    %mk=V   %sl=120
-E      6 2     0 7     9        %na=patient_in %mk=V   %sl=117
-E      7 1     0 8     9        %na=still_sick %mk=V   %sl=117
-E      6 1     0 9     9        %na=still_well %mk=V   %sl=115
-E      7 2     0 10    10       %na=patient_doctor     %mk=V   %sl=120
-E      8 2     0 11    9        %na=patient_out        %mk=V   %sl=115
-N 1    120     %sl=113
-L              1 1     14 "next_seed"  %mk=V
-E      0 3     1 2     4        %na=old-seed   %mk=V   %sl=113
-N 2    104     %sl=115
-E      0 9     2 1     9        %na=old-still_well     %mk=V   %sl=115
-E      0 11    2 2     9        %na=old-patient_out    %mk=V   %sl=115
-N 3    104     %sl=117
-E      0 8     3 1     9        %na=old-still_sick     %mk=V   %sl=117
-E      0 7     3 2     9        %na=old-patient_in     %mk=V   %sl=117
-N 4    104     %sl=118
-E      0 5     4 1     9        %na=old-still_available        %mk=V   %sl=118
-E      0 4     4 2     9        %na=old-doctor_out     %mk=V   %sl=118
-N 5    104     %sl=120
-E      0 6     5 1     10       %na=old-still_examining        %mk=V   %sl=120
-E      0 10    5 2     10       %na=old-patient_doctor %mk=V   %sl=120
-N 6    120     %sl=115
-L              6 1     18 "well_persons"       %mk=V
-E      1 1     6 2     4        %na=seed       %mk=V   %sl=115
-E      2 1     6 3     9       %mk=V
-N 7    120     %sl=117
-L              7 1     21 "nurse"      %mk=V
-E      3 1     7 2     9       %mk=V
-E      4 1     7 3     9       %mk=V
-N 8    120     %sl=120
-L              8 1     25 "examinations"       %mk=V
-E      1 1     8 2     4        %na=seed       %mk=V   %sl=120
-E      5 1     8 3     10      %mk=V
-G      0       %sl=121
-E      1 1     0 1     26      %mk=V
-E      2 1     0 2     26      %mk=V
-N 1    107     %sl=122
-L              1 1     4 "1"   %mk=V
-E      0 7     1 2     30       %na=patient_in %mk=V   %sl=121
-N 2    107     %sl=123
-L              2 1     4 "1"   %mk=V
-E      0 4     2 2     30       %na=doctor_out %mk=V   %sl=122
-} 1 4 4 0 1 2 3        %sl=102
-E      0 1     1 1     9        %na=list_of_patients   %mk=V   %sl=104
-E      0 2     1 2     9        %na=list_of_doctors    %mk=V   %sl=108
diff --git a/spectral/salishan/doctors/sisal/doctors.sis b/spectral/salishan/doctors/sisal/doctors.sis
deleted file mode 100644 (file)
index c48e963..0000000
+++ /dev/null
@@ -1,125 +0,0 @@
-define doctors_office
-
-% These routines model a doctor's office. There is no global clock, no
-% global communication, and tasks have no a priori knowledge of events.
-% People fall sick and go to the doctor's office to be cured. They wait
-% in order of arrival to see the next available doctor. If no one is
-% waiting, the doctors wait in order for patients to arrive.
-%
-% Due to the deterministic nature of Sisal, we can not queue patients in
-% their order of arrival as this is nondeterministic. Instead, we modify
-% the problem description to queue patients in the order they fall sick.
-% Note the nurse still doesn't know when the next patient will arrive.
-% Furthermore, Sisal can not express the problem's mutually recursive
-% streams. We overcome this by encapsulating the three subtasks in an
-% iterative loop, forcing the subtasks to execute in step. We believe
-% this mode of execution is more restrictive than intended by the problem
-% description.
-
-type queue  = array [integer];
-type queue2 = array [array [integer] ];
-
-global random    (seed: integer  returns real)
-global next_seed (seed: integer  returns integer)
-
-% Take as input a seed and a queue of healthy persons. If the queue is
-% empty or no one has fallen sick (the if and elseif clauses),  return
-% a ghost and the queue; else, choose a patient to become sick and re-
-% turn his identity and the queue minus that patient.
-
-function well_persons (seed: integer; patients: queue
-               returns queue, queue)
-
-  let
-      x    := random(seed);
-      size := array_size(patients);
-      sick := floor(real(size) * x / 0.7) + 1
-  in 
-      if size = 0 | x = 0.7 then
-         patients, array queue []
-      else
-         array_remh(patients[sick: patients[size]]),
-         array [1: patients[sick]]
-      end if
-  end let
-
-end function % well_persons
-
-% Take as input a queue of patients and a queue of doctors. If the queue
-% of patients or the queue of doctors is empty (the  if  clause), return
-% the inputs and an empty queue of patient-doctor records;  else, remove
-% the first patient and doctor from their respective queues,  and return
-% the queue of sick persons with everyone moved up  one,  the  queue  of
-% doctors with everyone moved up one,  and a queue of the patient-doctor
-% identities.
-
-function nurse(patients: queue; doctors: queue
-       returns queue, queue2, queue)
-
-  let
-      n_patients := array_size(patients);
-      n_doctors  := array_size(doctors)
-  in
-      if (n_patients = 0) | (n_doctors = 0) then
-         patients, array queue2 [], doctors
-      else
-         array_setl(array_reml(patients), 1),
-         array [1: array [1: patients[1], doctors[1]]],
-         array_setl(array_reml(doctors), 1)
-      end if
-  end let
-
-end function % nurse
-
-% Take as input a seed and a queue of patient-doctor pairs.  If the queue
-% is empty or no one has been cured,return an  empty  queue  of  patients,
-% doctors, and the queue of patient-doctor pairs;  else, choose a patient-
-% doctor pair,  and return the patient's identity,  the doctor's identity,
-% the queue minus the chosen patient-doctor pair.
-
-function examinations (seed: integer; in_exam: queue2
-              returns queue2, queue, queue)
-
-  let 
-      x     := random(seed);
-      size  := array_limh(in_exam);
-      cured := floor(real(size) * x / 0.3) + 1
-  in 
-      if size = 0 | x >= 0.3 then
-         in_exam, array queue [], array queue []
-      else
-         array_remh(in_exam[cured: in_exam[size]]),
-         array [1: in_exam[cured, 1]],
-         array [1: in_exam[cured, 2]]
-      end if
-  end let
-
-end function % examinations
-
-function doctors_office (list_of_patients, list_of_doctors: queue
-                 returns stream[queue], stream[queue])
-
-  for initial
-    seed            := 0;
-    still_well      := list_of_patients;
-    patient_out     := array queue [];
-    still_sick      := array queue [];
-    patient_in      := array queue [];
-    still_available := list_of_doctors;
-    doctor_out      := array queue [];
-    still_examining := array queue2 [];
-    patient_doctor  := array queue2 []
-  while true repeat
-    seed            := next_seed(old seed);
-    still_well, patient_in :=
-       well_persons(seed, old still_well || old patient_out);
-    still_sick, patient_doctor, still_available :=
-       nurse(old still_sick      || old patient_in,
-             old still_available || old doctor_out);
-    still_examining, patient_out, doctor_out :=
-       examinations(seed, old still_examining || old patient_doctor)
-  returns stream of patient_in
-          stream of doctor_out
-  end for
-
-end function % doctors_office
diff --git a/spectral/salishan/hamming/sisal/hamming.if1 b/spectral/salishan/hamming/sisal/hamming.if1
deleted file mode 100644 (file)
index bcd3f29..0000000
+++ /dev/null
@@ -1,180 +0,0 @@
-T 1 1 0    %na=Boolean
-T 2 1 1    %na=Character
-T 3 1 2    %na=Double
-T 4 1 3    %na=Integer
-T 5 1 4    %na=Null
-T 6 1 5    %na=Real
-T 7 1 6    %na=WildBasic
-T 8 10
-T 9 0  4    %na=onedim
-T 10 6 4    %na=istream
-T 11 8 10      0
-T 12 8 4       11
-T 13 8 4       12
-T 14 3 13      11
-T 15 8 9       0
-T 16 8 4       15
-T 17 3 16      11
-T 18 4 4
-T 19 4 1
-T 20 4 10
-C$  C Faked IF1CHECK
-C$  D Nodes are DFOrdered
-C$  F Livermore Frontend   Version1.8
-G      14      "powers"        %sl=15
-E      1 1     0 1     10      %mk=V
-{ Compound   1   4
-G      0       %sl=18
-E      4 1     0 4     10       %na=b_stream   %mk=V   %sl=21
-E      2 1     0 5     10       %na=s_stream   %mk=V   %sl=20
-E      1 1     0 6     4        %na=token      %mk=V   %sl=21
-E      5 1     0 7     1       %mk=V
-N 1    105     %sl=19
-E      0 1     1 1     10       %na=in_stream  %mk=V   %sl=19
-L              1 2     4 "1"   %mk=V
-N 2    112     %sl=20
-E      0 1     2 1     10       %na=in_stream  %mk=V   %sl=20
-N 3    152     %sl=21
-E      1 1     3 1     4        %na=token      %mk=V   %sl=21
-E      0 2     3 2     4        %na=prime      %mk=V   %sl=21
-N 4    103     %sl=21
-L              4 1     4 "1"   %mk=V
-E      3 1     4 2     4       %mk=V
-N 5    132
-E      1 1     5 1     4        %na=token      %mk=V
-E      0 3     5 2     4        %na=n  %mk=V
-G      0       %sl=22
-E      1 1     0 1     1       %mk=V
-N 1    131     %sl=22
-E      0 6     1 1     4        %na=token      %mk=V   %sl=22
-E      0 3     1 2     4        %na=n  %mk=V   %sl=22
-G      0       %sl=23
-E      5 3     0 4     10       %na=b_stream   %mk=V   %sl=39
-E      5 2     0 5     10       %na=s_stream   %mk=V   %sl=38
-E      5 1     0 6     4        %na=token      %mk=V   %sl=22
-E      6 1     0 7     1       %mk=V
-N 1    105     %sl=25
-E      0 5     1 1     10       %na=old-s_stream       %mk=V   %sl=25
-L              1 2     4 "1"   %mk=V
-N 2    105     %sl=26
-E      0 4     2 1     10       %na=old-b_stream       %mk=V   %sl=26
-L              2 2     4 "1"   %mk=V
-N 3    108     %sl=28
-E      0 5     3 1     10       %na=old-s_stream       %mk=V   %sl=28
-N 4    129
-E      3 1     4 1     1       %mk=V
-{ Compound   5   1
-G      0
-E      0 1     0 1     4       %mk=V
-G      0       %sl=32
-E      3 1     0 1     4       %mk=V
-E      3 2     0 2     10      %mk=V
-E      3 3     0 3     10      %mk=V
-N 1    131     %sl=32
-E      0 2     1 1     4        %na=b_token    %mk=V   %sl=32
-E      0 6     1 2     4        %na=s_token    %mk=V   %sl=32
-N 2    129
-E      1 1     2 1     1       %mk=V
-{ Compound   3   1
-G      0
-E      0 1     0 1     4       %mk=V
-G      0       %sl=36
-E      0 6     0 1     4        %na=s_token    %mk=V   %sl=39
-E      1 1     0 2     10      %mk=V
-E      3 1     0 3     10      %mk=V
-N 1    112     %sl=38
-E      0 3     1 1     10       %na=old-s_stream       %mk=V   %sl=38
-N 2    152     %sl=39
-E      0 6     2 1     4        %na=s_token    %mk=V   %sl=39
-E      0 5     2 2     4        %na=prime      %mk=V   %sl=39
-N 3    100     %sl=39
-E      0 4     3 1     10       %na=old-b_stream       %mk=V   %sl=39
-E      2 1     3 2     4       %mk=V
-G      0       %sl=33
-E      0 2     0 1     4        %na=b_token    %mk=V   %sl=35
-E      0 3     0 2     10       %na=old-s_stream       %mk=V   %sl=34
-E      3 1     0 3     10      %mk=V
-N 1    112     %sl=35
-E      0 4     1 1     10       %na=old-b_stream       %mk=V   %sl=35
-N 2    152     %sl=35
-E      0 2     2 1     4        %na=b_token    %mk=V   %sl=35
-E      0 5     2 2     4        %na=prime      %mk=V   %sl=35
-N 3    100     %sl=35
-E      1 1     3 1     10      %mk=V
-E      2 1     3 2     4       %mk=V
-} 3 1 3 0 1 2  %sl=33
-E      2 1     3 1     4       %mk=V
-E      0 2     3 2     4        %na=b_token    %mk=V   %sl=33
-E      0 3     3 3     10       %na=old-s_stream       %mk=V   %sl=34
-E      0 4     3 4     10       %na=old-b_stream       %mk=V   %sl=35
-E      0 5     3 5     4        %na=prime      %mk=V   %sl=35
-E      0 6     3 6     4        %na=s_token    %mk=V   %sl=37
-G      0       %sl=29
-E      0 2     0 1     4        %na=b_token    %mk=V   %sl=31
-E      0 3     0 2     10       %na=old-s_stream       %mk=V   %sl=30
-E      3 1     0 3     10      %mk=V
-N 1    112     %sl=31
-E      0 4     1 1     10       %na=old-b_stream       %mk=V   %sl=31
-N 2    152     %sl=31
-E      0 2     2 1     4        %na=b_token    %mk=V   %sl=31
-E      0 5     2 2     4        %na=prime      %mk=V   %sl=31
-N 3    100     %sl=31
-E      1 1     3 1     10      %mk=V
-E      2 1     3 2     4       %mk=V
-} 5 1 3 0 1 2  %sl=29
-E      4 1     5 1     4       %mk=V
-E      2 1     5 2     4        %na=b_token    %mk=V   %sl=29
-E      0 5     5 3     10       %na=old-s_stream       %mk=V   %sl=30
-E      0 4     5 4     10       %na=old-b_stream       %mk=V   %sl=31
-E      0 2     5 5     4        %na=prime      %mk=V   %sl=31
-E      1 1     5 6     4        %na=s_token    %mk=V   %sl=32
-N 6    132
-E      5 1     6 1     4        %na=token      %mk=V
-E      0 3     6 2     4        %na=n  %mk=V
-G      0       %sl=42
-E      2 1     0 1     10      %mk=V
-N 2    107     %sl=43
-L              2 1     4 "1"   %mk=V
-E      0 6     2 2     18       %na=token      %mk=V   %sl=42
-E      0 7     2 3     19      %mk=V
-} 1 4 4 0 1 2 3        %sl=18
-E      0 3     1 1     10       %na=in_stream  %mk=V   %sl=19
-E      0 2     1 2     4        %na=prime      %mk=V   %sl=21
-E      0 1     1 3     4        %na=n  %mk=V   %sl=22
-X      17      "hamming"       %sl=47
-E      1 1     0 1     10      %mk=V
-{ Compound   1   4
-G      0       %sl=50
-L              0 3     4 "0"    %na=i  %mk=V   %sl=51
-E      1 1     0 4     10       %na=s_stream   %mk=V   %sl=52
-N 1    103     %sl=52
-L              1 1     4 "1"   %mk=V
-L              1 2     4 "1"   %mk=V
-G      0       %sl=53
-E      2 1     0 1     1       %mk=V
-N 1    116     %sl=53
-E      0 1     1 1     9        %na=primes     %mk=V   %sl=53
-N 2    131     %sl=53
-E      0 3     2 1     4        %na=i  %mk=V   %sl=53
-E      1 1     2 2     4       %mk=V
-G      0       %sl=54
-E      1 1     0 3     4        %na=i  %mk=V   %sl=55
-E      3 1     0 4     10       %na=s_stream   %mk=V   %sl=55
-N 1    141     %sl=54
-E      0 3     1 1     4        %na=old-i      %mk=V   %sl=54
-L              1 2     4 "1"   %mk=V
-N 2    105     %sl=55
-E      0 1     2 1     9        %na=primes     %mk=V   %sl=55
-E      1 1     2 2     4        %na=i  %mk=V   %sl=55
-N 3    120     %sl=55
-L              3 1     14 "powers"     %mk=V
-E      0 2     3 2     4        %na=n  %mk=V   %sl=55
-E      2 1     3 3     4       %mk=V
-E      0 4     3 4     10       %na=old-s_stream       %mk=V   %sl=55
-G      0       %sl=56
-E      1 1     0 1     10      %mk=V
-N 1    127     %sl=57
-E      0 4     1 1     20       %na=s_stream   %mk=V   %sl=56
-} 1 4 4 0 1 2 3        %sl=50
-E      0 2     1 1     9        %na=primes     %mk=V   %sl=53
-E      0 1     1 2     4        %na=n  %mk=V   %sl=55
diff --git a/spectral/salishan/hamming/sisal/hamming.sis b/spectral/salishan/hamming/sisal/hamming.sis
deleted file mode 100644 (file)
index 60343b3..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-define hamming
-
-type OneDim  = array[integer];
-type Istream = stream[integer];
-
-% Take as input an integer, n, and a set of primes, A, B, C, ... , and
-% return a stream of all integers less than or equal to n in order and
-% without duplicates of the form, (A ** i) * (B ** j) * (C ** k) * ...
-% The main routine calls powers for each prime. powers manipulates two
-% two streams of tokens:   s_stream, the stream of tokens generated by
-% the previous call to powers; and b_stream, the stream of tokens gen-
-% erated by the present call. By selecting the smaller of the heads of
-% b_stream and s_stream, the tokens are output in order.
-
-function powers(n, prime: integer; in_stream: Istream
-        returns Istream)
-
-   for initial
-       token    := stream_first(in_stream);
-       s_stream := stream_rest(in_stream);
-       b_stream := stream [token * prime]
-   while token < n repeat
-       token, s_stream, b_stream := 
-         let
-             s_token := stream_first(old s_stream);
-             b_token := stream_first(old b_stream)  
-         in
-             if stream_empty(old s_stream) then
-                b_token,
-                old s_stream,
-                stream_append(stream_rest(old b_stream), b_token * prime)
-             elseif b_token < s_token then
-                b_token,
-                old s_stream,
-                stream_append(stream_rest(old b_stream), b_token * prime)
-             else
-                s_token,
-                stream_rest(old s_stream),
-                stream_append(old b_stream, s_token * prime)
-             end if
-         end let
-   returns stream of token when token <= n
-   end for
-
-end function % powers
-
-function hamming (n: integer; primes: OneDim
-          returns Istream)
-
-   for initial
-       i        := 0;
-       s_stream := stream [1]
-   while i < array_size(primes) repeat
-       i        := old i + 1;
-       s_stream := powers(n, primes[i], old s_stream)
-   returns value of s_stream
-   end for
-
-end function % hamming
diff --git a/spectral/salishan/haskell.tex b/spectral/salishan/haskell.tex
deleted file mode 100644 (file)
index f3f6bb1..0000000
+++ /dev/null
@@ -1,1290 +0,0 @@
-\documentstyle[11pt]{article}
-\textheight=8.0in
-\textwidth=6.0in
-\topmargin=0.5in
-\oddsidemargin=0.5in
-\evensidemargin=0.5in
-\parskip=6pt plus2pt minus2pt
-
-\newcommand{\lam}{\lambda}
-\newcommand{\la}{\leftarrow}
-\def\ab#1{\langle#1\rangle}
-
-\begin{document}
-\title{Haskell Solutions to the Language Session Problems\\
-at the 1988 Salishan High-Speed Computing Conference}
-\author{Paul Hudak\\
-Steve Anderson\\[.2in]
-Yale University\thanks{This research was supported primarily by DOE grant FG02-86ER25012.}\\
-Department of Computer Science\\
-New Haven, CT}
-\maketitle
-
-\section{Introduction}
-
-Haskell is a new functional language, named after the logician Haskell
-B. Curry, that was designed by a 14-member international committee
-representative of the functional programming research community
-\cite{haskell}.\footnote{The committee members are Arvind (MIT), Brian
-Boutel (Victoria University of Wellington), Jon Fairbairn (Cambridge
-University), Joseph Fasel (Los Alamos National Laboratory), Paul Hudak
-(Yale University), John Hughes (Glasgow University), Thomas Johnsson
-(Chalmers Institute of Technology), Dick Kieburtz (Oregon Graduate
-Center), Rishuyar Nikhil (MIT), Simon Peyton-Jones (University College
-London), Mike Reeve (Imperial College), Philip Wadler (Glasgow
-University), David Wise (Indiana University), and Jonathan Young (Yale
-and MIT).} The committee was formed because it was felt that research
-and application of modern functional languages was being hampered by
-the lack of a common language.  The committee's goals were that
-Haskell should:
-\begin{enumerate}
-\item Be suitable for teaching, research, and applications, including 
-      building large systems.
-\item Be completely described via the publication of a formal syntax 
-      and semantics.
-\item Be freely available, such that anyone is permitted to implement 
-      the language and distribute it to whomever they please.
-\item Be based on ideas that enjoy a wide consensus.  
-\item Be useable as a basis for further programming language research.  
-\end{enumerate}
-
-Haskell is a general purpose, purely functional programming language
-exhibiting many of the recent innovations in programming language
-research, including higher-order functions, non-strict functions and
-data structures, static polymorphic typing, user-definable algebraic
-data types, pattern-matching, list comprehensions, a module system,
-and a rich set of primitive data types, including arbitrary and fixed
-precision integers, and complex, rational, and floating-point numbers.
-In addition it has several novel features that give it additional
-expressivness, including an elegant form of overloading using a notion
-of {\em type classes}, a flexible I/O system that unifies the two most
-popular functional I/O models, and an array datatype that allows
-purely functional, monolithic arrays to be constructed using ``array
-comprehensions.''
-
-The reader will note that we did not describe Haskell as a {\em
-parallel} programming language; indeed it is not.  However, much
-research in recent years has centered on the implementation of
-functional languages on parallel machines, including the building of
-special-purpose hardware such as dataflow and reduction machines.  We
-will say little about these issues here, other than noting how the
-solutions to the problems presented have considerable inherent
-parallelism.
-
-Given our space constraints, it is impossible for us to describe
-Haskell in its entirety; our goal is only to give the reader some
-familiarity with the language by giving solutions to the four language
-session problems presented at the 1988 Salishan Conference on
-High-Speed Computing.  The reader is referred to the Haskell Report
-\cite{haskell} for a complete definition of the language.  Of course,
-studying the solutions presented here will give the reader an idea of
-what programming in any of a number of modern functional languages is
-like; indeed, all of the solutions given have been run on our
-implementation of Alfl, a functional language designed and implemented
-at Yale.
-
-\section{Brief Overview of Haskell}
-
-In this section we will describe enough Haskell syntax to allow
-understanding the programs given later.  As a result, there are
-significant parts of Haskell that won't be described at all, most
-notably user-defined data types, modules, and I/O.
-
-Haskell is an ``equational'' language similar to
-Miranda\footnote{Miranda is a trademark of Research Software Ltd.},
-Hope, and several other modern functional languages.  A function is
-defined by a set of equations which can {\em pattern-match} against
-their arguments.  Lists are written {\tt [a,b,c]} with {\tt []} being
-the empty list.  An element {\tt a} may be added to the front of the
-list {\tt as} by writing {\tt a:as}.  Two lists may be appended
-together by {\tt l1++l2}.  Here is an example of pattern-matching:
-\begin{verbatim}
-    member x []     = False
-    '        (y:ys) = if x==y then True
-                              else member x ys
-\end{verbatim}
-The ``tick mark'' on the second line is a convenient abbreviation for
-the initial subsequence on the preceding line (so that the arity of
-the two equations is the same).
-
-A function {\tt f x = x+1} may also be defined ``anonymously'' with
-the expression \verb! \x -> x+1!, and thus \verb! (\x -> x+1) 2!
-returns {\tt 3}.
-
-{\em List comprehensions} are a concise way to define lists, and are
-best explained by example:
-\begin{verbatim}
-    [ (x,y) | x<-xs, y<-ys ]
-\end{verbatim}
-which constructs the list of all pairs whose first element is from
-{\tt xs}, and second is from {\tt ys}.  ``Infinite lists'' may also be
-defined, and thanks to lazy evaluation, only that portion of the list
-that is needed by some other part of the program is actually computed.
-Thus the infinite list of ones can be defined by:
-\begin{verbatim}
-    ones = 1 : ones
-\end{verbatim}
-The notation {\tt [a..b]} denotes the list of integers from {\tt a} to
-{\tt b}, inclusive, and {\tt [a..]} is the infinite ascending list of
-integers beginning with {\tt a}.
-
-There are many standard utility functions defined on lists.  Aside
-from {\tt member} defined earlier, the ones we need in this paper are
-the following:
-\begin{verbatim}
-    takewhile pred []   = []       -- takes elements of list while pred is true
-    '            (a:as) = if (pred a) then (a : takewhile pred as)
-                                        else []
-
-    foldl f a []   = a             -- folds list from left
-    '       (x:xs) = foldl f (f a x) xs
-
-    foldr f a []   = a             -- folds list from right
-    '       (x:xs) = f x (foldr f a xs)
-
-    zip   []     bs   = []         -- forms list of pairs from pair of lists
-    '     as     []   = []
-    '   (a:as) (b:bs) = (a,b) : zip as bs
-
-    nodups []   = []               -- removes duplicates from list
-    '    (x:xs) = x : nodups [ y | y <- xs, y /= x ]
-\end{verbatim}
-In Haskell, function application always has higher precedence than any
-infix operator, and thus ``{\tt a : takewhile pred as}'' is parsed as
-``{\tt a : (takewhile pred as)}.''  Note in {\tt zip} the use of {\em
-tuples}, which in Haskell are constructed in arbitrary but finite
-length by writing ``{\tt (a,b, ..., c)}'' (the parentheses are
-mandatory); tuples may be pattern-matched like lists.  Finally, note
-that for {\tt foldl} and {\tt foldr} the following relationships hold:
-\begin{verbatim}
-    foldl f a [x1, x2, ..., xn]  ==>  (f ... (f (f a x1) x2) ... xn)
-    foldr f a [x1, x2, ..., xn]  ==>  (f x1 (f x2 ... (f xn a) ... ))
-\end{verbatim}
-
-Haskell also has {\em arrays} and a special syntax for manipulating
-them.  A two-dimensional array {\tt a} is indexed at position {\tt
-(i,j)} via the expression {\tt a!(i,j)}.  New arrays are constructed
-using the primitive function {\tt array}, which takes a set of bounds
-and a list comprehension as arguments; the list comprehension
-specifies the set of index/value pairs for the new array.  For
-example:
-\begin{verbatim}
-    array ((1,1),(n,n))
-      [ ((i,j) , k*a!(i,j)) | i<-[1..n], j<-[1..n] ]
-\end{verbatim}
-returns a nXn matrix representing the matrix {\tt a} multiplied by the
-scalar {\tt k}.
-
-This description of Haskell is quite brief, but should be enough
-to make the programs given later self-explanatory.  Nevetheless,
-experience with at least one other functional language would be
-beneficial.
-
-\section{Hamming's Problem (Extended)}
-
-\begin{quotation}
-``Given as input a finite increasing sequence of primes
-$\ab{a,b,c,...}$ and an integer $n$, output in order of increasing
-magnitude and without duplication all integers less than or equal to
-$n$ of the form:
-\[ a^i b^j c^k...,\ \ \ i,j,k,...\geq 0 \]
-Notice that if $m$ is in the output sequence then so are:
-\[ am,\ bm,\ cm,\ ...\ \leq n \]
-Our intention in posing the problem is to see how each language
-expresses such mutually recursive stream computations.''
-\end{quotation}
-
-A natural way to solve this problem in Haskell is to generate an
-infinite increasing sequence of hamming numbers, and then filter out
-those less than $n$.  But how do we create that infinite sequence?  To
-start, let's define a function {\tt scale} that multiplies every
-element in a stream by a certain number:
-\begin{verbatim}
-    scale p xs = [ p*x | x<-xs ]
-\end{verbatim}
-
-\begin{figure}
-\vspace{2.5in}
-\caption{Naive Hamming Solution}
-\label{h1}
-\vspace{3.5in}
-\caption{Hamming Solution Without Duplicates}
-\label{h2}
-\end{figure}
-
-Now note that a constructive way to express the problem is as an
-inductive definition:
-\begin{itemize}
-\item 1 is in the output sequence.
-\item For each prime $p$, if $k$ is in the output sequence, then so is
-      $k*p$.
-\end{itemize}
-We can construct a dataflow diagram for this as shown in Figure
-\ref{h1}, where the repeating pattern has been highlighted in a
-box.  Capturing the box's functionality in a function {\tt f}, and using
-{\tt foldl} to ``unfold'' {\tt f} over the list of primes, we arrive at
-this straightforward program to realize the dataflow diagram:
-\begin{verbatim}
-    hamming primes = 
-        h where h = 1 : foldl f [] primes
-                f xs p = merge xs (scale p h)
-\end{verbatim}
-where {\tt merge} merges a list of streams in increasing numeric
-order.  Unfortunately, {\tt merge} must also {\em remove duplicates},
-since this simple definition will construct every permutation of the
-factors for a particular number.  For example, it will generate three
-12's: 2*2*3, 2*3*2, and 3*2*2.  This is of course inefficient, and
-we'd prefer a solution that avoided the extra multiplications.  
-
-The problem stems from the fact that the sub-streams are generated
-recursively from the {\em entire} list {\tt h}.  What we really want
-is something that ``chases its tail'' so as to avoid generating all of
-the combinations.  The dataflow diagram in Figure \ref{h2} in fact
-does just that -- note how the result of each merge is fed back only
-to itself, thus avoiding the duplicates.  As before we can express
-this result by abstracting the repeating functionality and using {\tt
-foldl}:
-\begin{verbatim}
-    hamming primes = 1 : foldl f [] primes
-                     where f xs p = h where
-                                    h = merge (scale p (1:h)) xs
-\end{verbatim}
-in which case {\tt merge} is defined simply by:
-\begin{verbatim}
-    merge (a:as) (b:bs) = if a<b then a : merge as (b:bs)
-                                 else b : merge (a:as) bs
-    '      [] bs = bs
-    '      as [] = as
-\end{verbatim}
-and the result is just:
-\begin{verbatim}
-    takewhile (\x -> x<n) (hamming primes)
-\end{verbatim}
-using the utility {\tt takewhile} defined in the introduction.
-
-Here is a sample output transcript, run on our Alfl implementation:
-\begin{verbatim}
-  takewhile (\x -> x<46) (hamming [2,3,5]);
-
-  Result: [1,2,3,4,5,6,8,9,10,12,15,16,18,20,24,25,27,30,32,36,40,45]
-\end{verbatim}
-
-\section{The Paraffin Problem}
-
-\begin{quotation}
-``The chemical formula for paraffin molecules is $C_iH_{2i+2}$.  Given
-an integer $n$, output without repetition and in order of increasing
-size, structural representations of all paraffin molecules for $i \leq
-n$.  Include all isomers, but no duplicates.  You may choose any
-representation for the molecules you wish, so long as it clearly
-distinguishes among isomers.''  The problem is discussed in:
-\begin{quotation}
-Turner, D. A., The semantic elegance of  applicative  languages.
-Proc. Conf. on Functional Programming Languages and Computer Architecture, 
-Portsmouth, NH, 1981 Oct., pp. 85-92.
-\end{quotation}
-\end{quotation}
-
-This problem was solved in the above reference using the functional
-language Miranda, which happens to be similar to Haskell, and thus our
-job is already done for us!  Actually there are more efficient
-algorithms for solving this problem, but no more insight into
-understanding Haskell will be gained by giving them.  Thus we will
-simply rewrite Turner's KRC solution in Haskell (we also made a few
-simplifications), and refer to the paper referenced above for a
-detailed description of it:
-
-\begin{verbatim}
-    main = foldr (++) [] (map paraffin [1..])
-
-    paraffin n = quotient equiv [ [x,"H","H","H"] | x <- para (n-1) ]
-
-    para = ["H"] : map genpara [1..]
-    genpara n = [ [a,b,c] | i <- [0..(n-1)/3], j <- [i..(n-1-i)/2],
-                            a <- para!!i, b <- para!!j, c <- para!!(n-1-i-j)]
-
-    equiv a b = member (equivclass a) b
-    equivclass x = closure_under_laws [invert, rotate, swap] [x]
-
-    invert [[a,b,c],d,e,f] = [a,b,c,[d,e,f]]
-    '          ("H":x)     = "H":x
-
-    rotate [a,b,c,d] = [b,c,d,a]
-    swap   [a,b,c,d] = [b,a,c,d]
-
-    closure_under_laws fs xs = xs ++ closure' fs xs xs
-    closure' fs xs ys = closure'' fs xs (nodups [a | f <- fs, a <- map f ys,
-                                                     not (member a xs) ])
-    closure'' fs xs [] = []
-    '               ys = ys ++ closure' fs (xs ++ ys) ys
-
-    quotient f []   = []
-    '         (a:x) = a : [ b | b <- quotient f x, not (f a b) ]
-\end{verbatim}
-
-\section{A Doctor's Office}
-
-\begin{quotation}
-``Given a set of patients, a set of doctors, and a receptionist, model
-the following interactions: Initially, all patients are well, and all
-doctors are in a queue awaiting sick patients.  At random times,
-patients become sick and enter a queue for treatment by one of the
-doctors.  The receptionist handles the two queues, assigning patients
-to doctors in a first-in-first-out manner.  Once a doctor and patient
-are paired, the doctor diagnoses the illness and, in a randomly chosen
-period of time, cures the patient.  Then, the doctor and patient
-return to the receptionist's desk, where the receptionist records
-pertinent information.  The patient is then released until such time
-as he or she becomes sick again, and the doctor returns to the queue
-to await another patient.
-
-You may use any distribution functions you wish to decide when a patient
-becomes  sick  and  how  long a patient sees a doctor, but the code that
-models doctors must have no knowledge of the distribution  function  for
-patients,  and  vice  versa,  and  that for the receptionist should know
-nothing of either.  The receptionist  may  record  any  information  you
-wish:  patient's name, doctor assigned, illness, cure, wait times, queue
-lengths, etc.  The purpose of  the  problem  is  to  evaluate  how  each
-language expresses asynchronous communications from multiple sources.''
-\end{quotation}
-
-Of the four problems, this is probably the least well-defined.  The
-main difficulty lies in just what is meant by the verb ``model'' in
-the first sentence.  Perhaps the most common kind of modelling is a
-simulation of the actual time/event pairs, and that is what the first
-solution (written by Joe Fasel) presented below does.  However, such a
-solution removes completely the non-determinism and asynchrony of the
-problem (since they are being simulated), which conflicts somewhat
-with the statement made in the {\em last}\/ sentence of the problem
-description.  Thus we also provide a solution that uses explicit
-non-determinism.  Unfortunately, non-determinsm is not part of the
-Haskell standard, and thus we assume a primitive operator called {\tt
-choose} which non-determistically chooses an element from a list.
-
-The two solutions are radically different, and reflect very different
-characteristics of Haskell.
-
-\subsection{Time/event Simulation}
-
-This model of the doctors' office takes as input a number of patients,
-a number of doctors, an initial list of times at which patients get
-sick, and two infinite lists of durations, representing the
-distributions of times that patients remain well and of the times
-doctors take to cure patients.  An infinite list of tuples is
-returned, containing the following information for each office visit:
-\begin{verbatim}
-     (patient, sick-time, doctor, start-treatment-time, cure-time)
-\end{verbatim}
-That is, a patient number, the time the patient got sick and entered
-the patient queue, the number of the doctor assigned, the time at
-which the patient was assigned a doctor, and the time the doctor
-finished treating the patient.
-
-The style of this solution is to create mutually recursive streams of
-time/event pairs, merging them together at appropriate places while
-preserving the temporal order.  The main streams of events are
-patients ({\tt patientQ}), doctors ({\tt doctorQ}), and cured people
-({\tt cured}), as shown below.  {\tt insert} and {\tt makeQ} are
-utilities for handling queues of time-event pairs.
-
-\begin{verbatim}
-  doctors n m initialWellDist WellDist CureDist = cured
-
-  where insert y    [] = [y]         -- insert y into time-ordered queue
-        '   (p',t') rest@((p,t):xs) | t'<t = (p',t') : rest
-        '                                  = (p,t)   : insert (p',t') xs
-
-        makeQ (x:xs) yys             -- initial queue (in order),
-                                     -- subsequent entries (not in order)
-            = x : makeQ (insert y xs) ys where y:ys = yys
-    
-
-        patientQ                     -- [(patient, sick-time)]
-            = makeQ (foldr insert [] (zip [1..n] initialWellDist))
-                    [(p,c+x) | ((p,s,d,t,c),x) <- zip cured wellDist]
-    
-
-        doctorQ                      -- [(doctor, time-available)]
-            = makeQ [(d,0) | d <- [1..m]]
-                    [(d,c) | (p,s,d,t,c) <- cured]
-        cured
-            = [(p,s,d,t,t+x) where t = max s a
-               | ((p,s),(d,a),x) <- zip3 patientQ doctorQ cureDist]
-\end{verbatim}
-
-\subsection{Asynchronous Process Model}
-
-In the following solution the ``world'' is modelled as a 6-tuple:
-\begin{verbatim}
-    [healthy_people, -- list of healthy people
-     sick_people,    -- queue of sick people
-     being_cured,    -- list of sick-people/doctor pairs
-     cured_people,   -- queue of cured-people/doctor pairs
-     doctor_q,       -- queue of available doctors
-     record]         -- receptionist's record of pertinent data
-\end{verbatim}
-This representation is actually more detailed, and thus more
-realistic, than the previous one.  In particular, note the presence of
-a record book, as well as a queue to hold the doctor/patient pairs
-reporting back to the receptionist after a curing session (this queue
-is not called for in the specification, but seems more realistic).
-The initial state of the world should be obvious:
-\begin{verbatim}
-    initial_world = ([1..n], -- everybody's healthy     
-                     [],     -- nobody's sick           
-                     [],     -- nobody's being cured    
-                     [],     -- nobody's just been cured
-                     [1..m], -- every doctor is idle    
-                     [])     -- no record of curing     
-\end{verbatim}
-
-The dynamics of this model are captured by three ``processes'' that
-operate non-deter\-ministically (i.e.\ asynchronously) and in
-parallel.  Each process takes as input a world and outputs a ``new''
-world.  Simulation of the doctors office proceeds by starting with the
-initial world and iteratively choosing a process non-deterministically
-with which to generate a new world on each step of the simulation.
-The result is an infinite stream of worlds.
-
-\begin{verbatim}
-  doctors world = choose_loop world processes
-
-  processes = [sickening_process, curing_process, receptionist]
-
-  sickening_process w@([],s,b,c,d,r) = w              -- everybody's sick!!
-  '                 w@(h, s,b,c,d,r) = (hs,p:s,b,c,d,r)
-                                       where (p,hs) = sicken_one h
-
-  curing_process w@(h,s,[],c,d,r) = w                 -- nobody being cured
-  '              w@(h,s,b, c,d,r) = (h,s,dps,dp:c,d,r)
-                                    where (dp,dps) = cure_one b
-                         
-
-  receptionist w = choose [help_the_sick,move_the_cured] w
-    where help_the_sick w@(h,[],  b,c,d,   r) = w     -- nobody's sick
-          '             w@(h,s,   b,c,[],  r) = w     -- no free doctors
-          '             w@(h,p:ss,b,c,d:ds,r) = (h,ss,(d,p):b,c,ds,r)
-
-          move_the_cured w@(h,s,b,[],       ds,r) = w -- no recent curing
-          '              w@(h,s,b,(d,p):dps,ds,r) = 
-                                            (p:h,s,b,dps,ds++[d],(d,p):r)
-
-  cure_one   = choose_and_remove   -- random curing function
-  sicken_one = choose_and_remove   -- random sickening function
-
-  choose_and_remove lst = (el, [y | y<-lst, y\=el])
-                          where el = choose lst
-
-  choose_loop obj fs = new_obj : choose_loop new_obj fs
-                       where new_obj = choose fs obj
-\end{verbatim}
-Note that the non-deterministic utility functions are built from a
-single non-deterministic primitive called {\tt choose} that
-non-deterministically selects an element from a list.
-
-This non-deterministic process model, by the way, could be made
-deterministic by providing lists of sickness and wellness
-distributions as in the time/event simulation.  Similarly, the
-time/event simulation could be made non-deterministic by suitably
-merging the event streams non-deterministically.
-
-\section{Skyline Matrix Solver}
-
-\begin{quotation}
-``Solve the system of linear equations:
-\[ A\ x = b \]
-where $A$ is an $n$ by $n$ skyline matrix.  A skyline matrix has
-nonzero elements in column $j$ in rows $i$ through $j$, $1 \leq i \leq
-j$, and has nonzero elements in row $i$ in columns $j$ through $i$, $1
-\leq j \leq i$.  The first constraint defines the skyline above the
-diagonal, which is towards the top, and the second constraint defines
-the skyline below the diagonal, which is towards the left.  For
-example, if
-\[ A\ = \left[
-       \begin{array}{ccccccc}
-       X & 0 & 0 & x & 0 & 0 & 0 \\
-       0 & X & 0 & x & 0 & x & 0 \\
-       0 & x & X & x & x & x & 0 \\
-       0 & 0 & 0 & X & x & x & 0 \\
-       0 & x & x & x & X & x & 0 \\
-       0 & 0 & 0 & x & x & X & 0 \\
-       0 & 0 & 0 & 0 & 0 & 0 & X 
-
-       \end{array}
-       \right]
-\]
-then the $i$ vector of the first constraint is:
-\[ \ab{1,2,3,1,3,2,7} \]
-and the $j$ vector of the second constraint is:
-\[ \ab{1,2,2,4,2,4,7} \]
-You may assume any input form for $A$ and $b$ you wish, and you may
-assume the $i$ and $j$ vectors as input parameters.  A rather obscure
-reference for the problem (available on request) is:
-\begin{quotation}
-Eisenstat, S.C., and Sherman, A.H. {\em Subroutines for envelope solution  
-of 
-sparse linear systems}.  Research Report 35, Yale University, New Haven  
-CT, 
-October 1974.
-\end{quotation}
-The intention of this problem is to test each language's ability to
-manipulate arrays, to use the structure of arrays to avoid unnecessary
-computations, and to express array operations.''
-\end{quotation}
-
-Our understanding of this problem was aided greatly not only by the
-above tech report, but also a copy of some Fortran code written by
-Andy Sherman which implements an envelope method for solving a linear
-system.  That code, complete with documentation, is also listed in the
-Appendix of \cite{huda88f}.
-
-Having Sherman's code provided us with an opportunity to study
-Fortran-style {\em incremental} array manipulations in a functional
-language, and to contrast that with the preferred {\em monolithic}
-array approach.  We think the results are quite interesting.  To
-conduct the study we first converted, as faithfully as possible, the
-Fortran code into Haskell using incremental updates to purely
-functional arrays (see \cite{huda87b} for a discussion of incremental
-arrays).  We then rewrote the program in a monolithic style, adhering
-more closely to the matrix algebra, but using the same envelope
-representations used by Sherman.
-
-The incremental functional array solution is presented in
-\cite{huda88f}, and illustrates how one {\em could} do incremental
-array operations in a functional language that ``have the feel'' of
-side effects to arrays in an imperative language.  In fact, the
-incremental program, when run on our Alpha-Tau implementation of Alfl
-\cite{huda84b}, achieves the same space complexity as the Fortran
-program.  That is, our optimizer is able to infer that every array is
-``single-threaded'' and thus updates can be done destructively rather
-than by copying.
-
-On the other hand, this is not the {\em preferred} way to program with
-arrays in a functional language.  Haskell has a primitive data type
-for arrays together with special syntax that allows the specification
-of an array instance {\em monolithically} rather than incrementally.
-That is, the entire final array is specified in one monolithic
-declaration, yielding a declarative reading more in line with the
-philosophy of functional programming.  This style of solution is
-presented below.
-
-\newcommand {\bmba}[1]  { \[ \begin{array}{#1} }
-\newcommand {\eaem}     { \end{array} \] }
-\newcommand {\belongs}  { \epsilon }
-
-\subsection{Monolithic Array Solution}
-
-The skyline problem illustrates well some of the special strengths of
-Haskell arrays.  In particular, the array specifications can be
-derived from the original mathematical definition of the problem in a
-clear and straightforward way.  The essential data dependences are
-clear, rather than obscured by extraneous operational sequencing.  The
-recursive definition of arrays, including mutually recursive
-definitions of multiple arrays, permit elegant specifications as well
-as efficient implementations.  Haskell arrays permit separate
-definitions for elements in different regions of an array, which
-permits optimizations similar to the lifting of computations from
-Fortran loops, and which clearly correspond to the mathematical
-function domain specifications.
-
-The incremental solution was essentially a transcribed version of
-Sherman's code, and thus we included no description of the data
-representations or the algorithm.  For the monolithic solution we will
-instead start from the very basics, and develop the final program via
-step-wise refinement of the specification.
-
-\subsubsection{Introduction to Sherman's envelope format for sparse  
-matrices.}
-
-Sherman's envelope format works best when the sparse linear system
-{\tt A*x = b} has its equations and variables ordered such that most
-of {\tt A}'s nonzeros are close to the main diagonal.  Each row {\tt
-i} of the lower triangle is stored as an envelope from the leftmost
-nonzero in the row up to the last column {\tt j = i-1} before the
-diagonal.  Likewise, each column {\tt j} of the upper triangle is
-stored as an envelope from the uppermost nonzero in the column down to
-the last row {\tt i = j-1} before the diagonal.  The main diagonal
-itself is stored as a 1-D vector of length {\tt n}.
-
-Sherman represents a sparse matrix as the 5-tuple {\tt (n, pl, d, pu,
-irl, iru)} where:
-\begin{itemize}
-\item   {\tt n} = the order of {\tt A}.
-
-\item   {\tt pl, d, pu} = 1-D floating point vectors representing
-        the lower triangle's consecutively stored row envelopes,
-        the main diagonal elements,
-        and the upper triangle's consecutively stored column envelopes.
-
-\item   {\tt irl, iru} = 1-D length {\tt n} integer vectors of
-        base addresses into {\tt pl} and {\tt pu}.
-\end{itemize}
-
-    The base address vectors require some explanation.  For  access into
-lower triangle {\tt pl}, suppose we defined the vectors:
-\begin{itemize}
-\item   {\tt fl!i} = the column index of the first nonzero in row {\tt i};
-\item   {\tt begin\_l!i} = the index into {\tt pl} of row {\tt i}'s first
-        nonzero.
-\end{itemize}
-Then we would access {\tt a!(i,j)} in the lower triangle by
-{\tt pl!(begin\_l!i + j - fl!i)  =  a!(i,j).}
-But the value {\tt begin\_l!i - fl!i} is the same for every {\tt j}
-in row {\tt i}.  In a later section we will see that computing an element
-{\tt (i,j)} of either the lower or upper triangle factor requires an
-inner product summation that runs along the lower triangle's row {\tt i}
-and the upper triangle's column {\tt j}.  For a sequential program
-it is desirable to make this summation the innermost loop to preserve
-locality of reference and therefore achieve good cache and virtual
-memory hit rates.  Therefore we would like to raise this
-loop-invariant computation out of the innermost loop,
-replacing the $O(n^2)$ evaluations of the expression
-{\tt begin\_l!i - fl!i} by $O(n)$ evaluations.
-We also save space in the representation
-by replacing the $2$ length-$n$ vectors with a single length-$n$ vector.
-\begin{verbatim}
-    irl!i           =  begin_l!i - fl!i
-    pl!(irl!i + j)  =  a!(i,j).
-\end{verbatim}
-The value {\tt irl!i} can be thought of as the row {\tt i} envelope's
-base address into {\tt pl}.  The ``first nonzero" function {\tt fl} is
-useful as a limit for the summation over all {\tt j} in row {\tt i},
-but can be easily recovered from {\tt irl}. The upper triangle's
-column-oriented envelopes are stored in a similar fashion.
-
-\subsubsection{The ``first nonzero" functions.}
-
-We will show how the first nonzero function {\tt fl} for the row-oriented
-envelopes in the lower triangle can be recovered from the vector {\tt  
-irl}.
-A similar function {\tt fu} can be derived for the column-oriented
-upper triangle envelopes.
-
-The last column stored for row {\tt i} is {\tt j = i-1}.  Let {\tt
-(pl\_env\_len i)} = the row {\tt i} envelope size.  Then the column
-index of row {\tt i}'s first nonzero is
-\begin{verbatim}
-    fl i  =  i - (pl_env_len i).
-\end{verbatim}
-The index values {\tt (irl!i-1 + i-2)} and {\tt (irl!i + i-1)} into {\tt
-pl} point to the end of the row {\tt i-1} and row {\tt i} envelopes
-respectively.  Since the envelopes are stored consecutively in {\tt
-pl}, we have
-\begin{verbatim}
-    pl_env_len i  =  (irl!i + i-1) - (irl!(i-1) + i-2),
-\end{verbatim}
-therefore,
-\begin{verbatim}
-    fl i  =  i - 1 + irl!i-1 - irl!i.
-\end{verbatim}
-
-Since there is no {\tt irl!0} entry, {\tt fl} is only defined for
-{\tt i <- [2..n]},   The row 1 envelope is always empty in the lower
-triangle.  For an empty row the first nonzero is in column {\tt (fl i) =  
-i};
-so the envelope contains columns {\tt j <- [(fl i)..(i-1)] =} $\phi$.
-
-We could put a conditional in {\tt fl} to make it defined for row $1$,
-but this imposes a run-time test for every row.  A better alternative
-is to define a bogus {\tt irl!0} that causes {\tt (fl 1)} to return $1$.
-Entry {\tt irl!1} always has the value
-{\tt irl!1 = (begin\_l 1) - (fl 1) = 1 - 1 = 0},
-therefore {\tt irl!0} must satisfy the equation:
-\begin{verbatim}
-    1  =  fl 1  =  1 - 1 + irl!0 - irl!1  =  irl!0.
-\end{verbatim}
-However, we will discover later that we can always avoid any calls to
-{\tt fl} for row 1, or to {\tt fu} for column 1.
-
-
-\subsubsection{A functional derivation of $L*U$ factorization.}
-
-The problem is to solve the linear system $A*x = b$: given $A$
-and $b$, what is $x$?  If $A$ is invertible, there exists
-a unique factorization $A = L*U$ where $L$ is lower triangular
-and $U$ is unit upper triangular, which reduces the original
-problem to the easier problem of solving the triangular linear systems
-$L*y = b,\ U*x = y$.
-
-But this leaves the problem: given $A$, what are $L$ and $U$?
-The usual derivation of $L$ and $U$ is presented as a
-sequence of steps $k\ \belongs\ [1..n]$, each step forming an intermediate
-matrix $A(k)$; this particular sequential approach to Gaussian
-elimination is very obscure, hiding the essential data dependences
-under non-essential operational details.  Instead we will first write
-out the equation $A = L*U$ as if we were finding $A$
-given $L$ and $U$, then by algebraic manipulation, derive
-mutually recursive equations for $L$ and $U$ given $A$.
-We will see that the Haskell program mimics closely the mathematical
-notation we use to derive the equations for $L$ and $U$.  Because
-of this close resemblance, the program is easy to reason about, the
-essential data dependences are clear, and it is easy to justify and
-debug optimizations.
-
-Each $a(i,j)$ is the inner product of $l$'s row $i$ and $u$'s
-column $j$:
-$ 
-    a(i,j)\ =\ \sum_{k=1}^n l(i,k)*u(k,j),
-    \ \ i\ \belongs\ [1..n], \ j\ \belongs\ [1..n]
-$.
-But there is no contribution to $a(i,j)$ for terms in which $l(i,k) = 0$
-(for columns $k$ to the right of the diagonal: $i < k$) or in which
-$u(k,j) = 0$ (for rows $k$ below the diagonal: $j < k$).  Therefore,
-instead of summing over $k\ \belongs \ [1..n]$, we only need to sum over
-$k\ \belongs \ [1..(min\ i\ j)]$.
-
-Equivalently, we can separate the definitions for $a(i,j)$ in the
-lower triangle and diagonal ($i \leq j$, and therefore use $j$
-as the summation limit):
-\bmba{rlll}
-    a(i,j)  & =  \sum_{k=1}^{j} l(i,k)*u(k,j)   &                   \\
-            & =  l(i,j)*u(j,j) + \sum_{k=1}^{j-1} l(i,k)*u(k,j),
-                & \ \ i \ \belongs \ [1..n],\ j \ \belongs \ [1..i],    \\
-\eaem
-or in the upper triangle ($i < j$, and therefore use $i$ as 
-the summation limit).
-\bmba{rlll}
-    a(i,j)  & =  \sum_{k=1}^{i} l(i,k)*u(k,j)   &                   \\
-            & =  l(i,i)*u(i,j) + \sum_{k=1}^{i-1} l(i,k)*u(k,j),
-                & \ \ i \ \belongs \ [1..n],\ j \ \belongs \ [i+1..n].
-\eaem
-
-But we can immediately rearrange these equations to define the elements
-of $L$ and $U$ (recall that we require $u(j,j) = 1.0$ for all $j$):
-\bmba{rll}
-    l(i,j)
-            & =  a(i,j) - \sum_{k=1}^{j-1} l(i,k)*u(k,j),
-                & \ \ i \ \belongs \ [1..n],\ j \ \belongs \ [1..i],    \\
-    \\
-    u(i,j)
-            & =  (\ a(i,j) - \sum_{k=1}^{i-1} l(i,k)*u(k,j)\ ) \ / \ l(i,i),
-                & \ \ i \ \belongs \ [1..n],\ j \ \belongs \ [i+1..n].
-\eaem
-
-The $L$ equations show us that whatever the operational sequencing,
-$l(i,j)$ depends on $a(i,j)$ and recursively depends on
-other $L$ elements in the same row $i$ and to the left,
-and on $U$ elements in the same column $j$ and above. 
-
-The recursion terminates upon the leftmost column of $L$ and the
-topmost row of $U$.  Similar reasoning holds for the $U$
-equation.
-
-In the following we will replace $l(i,i)$ with the name $d(i)$.
-There are optimizations we can perform on $L$'s diagonal
-elements that make them deserve special treatment.  The $d(i)$'s
-are {\em not} to be confused with the elements of diagonal matrix
-$D$ in the $L*D*U$ factorization, where both $L$ and $U$
-are unit triangular.
-
-\subsubsection{$L*U$ factorization in dense array format.}
-
-For clarity, we introduce some new syntax into list comprehensions.
-In an {\tt array} function's list comprehension argument, the {\tt
-(i,x)} pair can be written in the form {\tt i = x}, similar to the
-declarations in a Haskell {\tt where}.  For example,
-\begin{verbatim}
-    array ((1,1), (N,N))
-      [ (i,j) = k*a!(i,j) | i <- [1..N], j <- [1..N] ]
-\end{verbatim}
-
->From the equations in the previous section let us write a functional
-program to compute $L$ and $U$.  Let us define a higher-order function
-for the mathematical summation sign:
-\begin{verbatim}
-    sum i j accum f  =  if j<i then accum else sum (i+1) j (accum + (f i)) f
-\end{verbatim}
-Let us define a function {\tt l} that given index {\tt (i,j)},
-computes the element value in $L$:
-\begin{verbatim}
-    l (i,j)  =  a!(i,j) - (sum 1 (j-1) 0. l_exp)
-        where l_exp k  =  L!(i,k) * U!(k,j)
-\end{verbatim}
-This definition of {\tt l} is very similar to a DO loop in Fortran,
-and can be compiled as efficiently.
-
-Instead we will use an alternative definition of {\tt sum}
-that operates over a list.
-\begin{verbatim}
-    sum xs  =  sum1 0. xs
-    where
-        sum1 accum []      =  accum
-        sum1 accum (x:xs)  =  sum1 (accum+x) xs
-\end{verbatim}
-Used with a list comprehension argument,
-this version gives a somewhat more legible way of
-writing {\tt l i j}, and more closely resembles the mathematical
-summation sign.  
-\begin{verbatim}
-    l (i,j)  =  a!(i,j) - sum [ L!(i,k) * U!(k,j) | k <- [1..j-1] ]
-\end{verbatim}
-We can think of the list as a multiset, and of {\tt sum} as summing
-the elements of the set (although strictly speaking, floating point
-addition is not associative).  Techniques such as Wadler's
-listlessness and deforestation transformations can ensure that such an
-expression gets converted to a semantically equivalent expression in
-which the lists are eliminated; the expression can be compiled as
-efficiently as a DO loop (\cite{wadl84,wadl85b}).
-
-This definition of {\tt l} holds for {\tt i <- [2..n], j <- [1..i-1]}.
-Row 1 is skipped since {\tt l (1,1)} is on the diagonal and we wish to
-define the diagonal elements separately.
-
-    The definition for {\tt d}, which computes $L$'s diagonal elements,
-is a simplified version of the definition for {\tt l} above
-(since {\tt i = j}),  for {\tt i <- [1..n]}.
-
-The definition for $U$ is nearly the same as for $L$ except that summation
-stops at {\tt k = i-1}.  Then the entire row is scaled by
-{\tt 1./d!i} to normalize $U$'s diagonal to 1.0.
-$U$'s definition holds for {\tt i <- [1..n-1], j <- [i+1..n]},
-or equivalently, for {\tt j <- [2..n], i <- [1..j-1]}.  See the
-complete program at the end of this section.
-
-    Each element {\tt d!i} appears as a divisor in the definition for  
-every
-{\tt u!(i,j)} in the same row {\tt i} ($(n^2 - n)/2$ divisions  
-altogether),
-as well as in definition of {\tt x!i} in the same row for the $L*U*x = b$
-backsolve stage ($n$ divisions).  Since division is expensive compared  
-with
-multiplication, we instead store the inverse of each {\tt d!i}, replacing
-$O(n^2)$ divisions with $n$ divisions and $O(n^2)$ multiplications.
-This is a classic example of using an array to store expensive shared
-computations.
-
-    The definitions of $L$ and $U$ are mutually recursive, both
-in the mathematical definition and in the Haskell array definition.
-We do not need to store $L$'s upper or $U$'s lower triangle, which
-are zero, or $U$'s unit diagonal, so we can store all the essential
-results in a single $n^2$ array.
-We can recursively define the matrix {\tt lu}  $= (L-D) + D^{-1} + (U-I)$
-in dense matrix format (where $D$ = $L$'s diagonal,
-$D^{-1} = D$'s inverse):
-\begin{verbatim}
-    plu a  =  lu
-    where
-        ((1,1),(n,n)) = bounds a
-        lu = array ((1,1),(n,n))
-                [ (i,j) = l i j  | i <- [2..n], j <- [1..i-1] ]  ++
-                [ (i,i) = d i    | i <- [1..n] ]  ++
-                [ (i,j) = u i j  | i <- [1..n-1], j <- [i+1..n] ]
-        l i j  =  a!(i,j) - sum [ lu!(i,k) * lu!(k,j) | k <- [1..j-1] ]
-        d i    =  1./s
-            where s = a!(i,i) - sum [ lu!(i,k) * lu!(k,i) | k <- [1..i-1] ]
-        u i j  =  lu!(i,i) * ( a!(i,j)
-                    - sum [ lu!(i,k) * lu!(k,j) | k <- [1..i-1] ] )
-\end{verbatim}
-
-
-\subsubsection {Lazy arrays and strict arrays}
-
-Notice that the domain specifications in the the array comprehension
-correspond exactly to the domain specifications given in the mathematical
-function definitions.  These domain specifications should {\em not} be
-thought of as looping constructs: they say nothing about the order in
-which elements of the array {\tt lu} should be evaluated.
-
-In fact, we could let {\tt lu} be a {\em lazy array}.   Each element
-in a lazy array is represented by a thunk which is evaluated only when
-demanded.  Domain specifications such as {\tt i <- [2..n], j <- [1..i-1]}
-specify {\em where} thunks for a particular form of expression must be
-placed, but say nothing about the {\em order} in which the thunks are
-evaluated.
-
-Evaluation of an element in a lazy array is forced only when it is
-explicitly requested.  If a lazy array is recursively defined,
-evaluation of an element in turn forces the evaluation of other
-elements on which it has a data dependence.
-
-But if an element has already been forced once, the thunk modifies
-itself so that its value is returned immediately, without recomputation.
-We can think of an array {\tt a} as a function of {\tt d} integer  
-arguments
-(where {\tt d} is the the array's dimension), for which we know that
-any given function application ({\tt a }$\ i_1\ ...\ i_d$) (i.e.,
-any given array element {\tt a!}$(i_1,\ ...,\ i_d)$), will be requested
-many times.  In this view an array is a {\em caching function}.
-
-There are several essential differences between lazy arrays in Haskell
-and arrays in a language like Fortran.  Haskell specifies the result
-array monolithically in terms of a definition for each element,
-whereas Fortran specifies the result array in terms of incremental
-updates to the input array.  For the example program presented so far,
-Haskell's monolithic definition requires that the output array be
-computed in a separate space from the input array.
-
-For Haskell to be able to reuse the input array {\tt a} to store the
-output array {\tt lu}, the compiler must know that reuse is safe.
-There must no other outstanding references to {\tt a} outside the
-definition of {\tt lu}.  Furthermore, an element {\tt a!(i,j)} must
-be dead at the time that it is replaced by element {\tt lu!(i,j)},
-which means that either the compiler must determine or the programmer
-must specify a safe order of evaluation.  This research topic is 
-the subject of \cite{ande89} and \cite{ande89b}.
-
-Another difference is that the Fortran programmer must be careful to
-arrange the order of his computation so that whenever
-he evaluates an element {\tt lu!(i,j)}, the elements on which {\tt  
-lu!(i,j)}
-has a direct data dependence will have already been computed.
-Both the Haskell and the Fortran arrays can be viewed as cached
-functions, so although they may differ in the {\em order} in which
-array elements are evaluated, there is no difference in the {\em total
-amount} of computation time spent on array indexing and floating point
-arithmetic.  But Haskell's thunks increase the time by a small constant
-factor. In addition to computing the element values, we must also create
-a thunk for each element when array storage is allocated; and whenever
-an element is demanded we must test whether or not its thunk as been
-forced yet.
-
-Notice that we could eliminate the need for creating and testing element
-thunks if, like the Fortran programmer, we could guarantee a safe order
-of evaluation.  See \cite{ande89,ande89b}.
-
-
-\subsubsection{Refinement of $L*U$ factorization using ``first
-               nonzero'' information.}
-
-Notice that in the summations, the {\tt k}-th term {\tt l!(i,k) * u!(k,j)}
-makes no contribution if either factor is zero.  If a sparse matrix
-is organized such that most nonzeros are close to the main diagonal,
-considerable work can be saved by ignoring terms in which
-either {\tt l!(i,k)} falls to the left of row {\tt i}'s first nonzero
-or if {\tt u!(k,j)} falls above column {\tt j}'s first nonzero.
-In other words, skip terms for which {\tt k < (fl i)} or {\tt k < (fu  
-j)}).
-
-Assume we are given the ``first nonzero"
-functions {\tt fl} and {\tt fu}.  {\tt L} is then defined by:
-\begin{verbatim}
-    l (i,j)  =  a!(i,j) - sum [ lu!(i,k) * lu!(k,j) } | k <- [kmin_l..j-1] ]
-    where kmin_l   =  max (fl i) (fu j)
-\end{verbatim}
-
-We have defined {\tt l (i,j)} for {\tt i <- [2..n], j <- [1..(i-1)]}.
-But recall the domains of the first nonzero functions:
-{\tt (fl i)} is defined over {\tt i <- [2..n]}, which causes
-no problem, but {\tt (fu j)} is defined only over {\tt j <- [2..n]},
-which makes {\tt (l (i,j))} undefined in column $1$.
-
-We can put a run-time test in {\tt (fu j)} for the case column
-{\tt j = 1}, but then this test gets executed for every one of
-the $O(n^2)$ lower triangle elements.  But we notice that whenever
-{\tt j} is at or to the left of the row's first nonzero (i.e.,
-when {\tt j <= (fl i)}), the summation must terminate immediately.
-Then we are left with {\tt (l (i,j)) = a!(i,j)}, which is zero for
-{\tt j < (fl i)}, nonzero for {\tt j = (fl i)}.
-
-Therefore, when we know {\tt j <= (fl i)}, we can return {\tt a!(i,j)}
-immediately, avoiding calls to the summation altogether.  This case
-includes column {\tt j = 1}, so we do not need special treatment
-for this column.
-
-We partition the lower triangle into different regions
-which use separately tailored element definitions.
-\begin{verbatim}
-    lu = array ((1,1),(n,n))
-            [ (i,j) = l i j  | i <- [2..n], j <- [(fl i)+1..i-1] ]  ++
-            [ (i,j) = a[i,j] | i <- [2..n],
-                                j <- [ (fl i) ], j < i ]  ++
-            [ (i,j) = 0.0    | i <- [2..n], j <- [1..(fl i)-1] ]
-            . . .
-\end{verbatim}
-Similar partitionings hold for the diagonal and upper triangle.
-These clauses partition the lower triangle into three regions:
-\begin{enumerate}
-\item   {\tt  j <- [(fl i)+1..i-1] } :
-        inside the envelope except for the envelope's first column
-        (the empty set if first nonzero is on or immediately beside
-        the diagonal),
-
-\item    {\tt  j <- [ (fl i) ], j < i } :
-        the envelope's first column
-        (the empty set if first nonzero is on the diagonal).
-
-\item    {\tt  j <- [1..(fl i)-1] } :
-        outside the envelope
-        (the empty set if first nonzero is in column 1).
-        These zero elements of {\tt a} are guaranteed not to fill in
-        for {\tt lu}.
-\end{enumerate}
-
-
-\subsubsection{$L*U$ factorization using envelope representation.}
-
-Finally let us convert our definitions from dense format to envelope
-format.  Let input matrix {\tt a} be represented by the tuple {\tt (n,
-old\_pl, old\_d, old\_pu, irl, iru)} and result matrix {\tt lu} be
-represented by {\tt (n, new\_pl, new\_d, new\_pu, irl, iru)}.
-
-The auxiliary vectors {\tt iru} and {\tt irl} are the same for
-both input matrix {\tt a} and output matrix {\tt lu}.  Zero elements
-in {\tt a} that become non-zero in {\tt lu} are called {\em fill-in}.
-Fill-in can occur only inside the envelope; all zeroes outside
-{\tt a}'s envelope are guaranteed to remain zero in {\tt lu} and
-are therefore also outside {\tt lu}'s envelope; therefore {\tt a}
-and {\tt lu} have the same envelope structure, as represented
-by vectors {\tt iru} and {\tt irl}.
-
-The vector bounds for {\tt new\_d} are simply {\tt (1,n)}.
-We can get the new vector bounds for {\tt new\_pl} (and similarly
-for {\tt new\_pu} by fetching the old vector bounds: {\tt (bounds pl)}.
-Alternatively, we can observe that the index of {\tt pl}'s last element
-is {\tt irl!n + n - 1}.
-
-Example substitutions for references to the input matrix {\tt a} are:
-\begin{list}{}
-    \item When {\tt i <- [2..n], j <- [(fl i)..(i-1)]},     \\
-        {\tt a!(i,j)} becomes {\tt old\_pl!(irl!i + j)}.
-    \item When {\tt i <- [1..n]},                           \\
-        {\tt a!(i,i)} becomes {\tt old\_d!(i)}.
-    \item When {\tt j <- [2..n], i <- [(fu j)..(j-1)]},     \\
-        {\tt a!(i,j)} becomes {\tt old\_pu!(i + iru!j)}.
-\end{list}
-Similar substitutions can be made for references to
-{\tt l}, {\tt d}, and {\tt u} regions of {\tt lu!(i,j)}.
-The definition of the lower triangle then becomes:
-\begin{verbatim}
-    l (i,j)   = s
-        where
-            kmin_l      =  max (fl i) (fu j)
-            l_exp k     =  new_pl!(irl!i + k) * new_pu!(k + iru!j)
-            accum_init  =  old_pl!(irl!i + j)
-            s           = a_init - sum [ l_exp k | k <- [kmin_l..j-1] ]
-
-    new_pl  = array (bounds old_pl)
-                [ irl!i+j  =  l (i,j)
-                        | i <- [2..n], j <- [(fl i)+1..i-1] ]  ++
-                [ irl!i + j  =  old_pl!(irl!i + j)
-                        | i <- [2..n], j <- [(fl i)], j < i ]
-\end{verbatim}
-
-There are many opportunities for common subexpression
-elimination.  For a given element {\tt (l (i,j))}, every term {\tt k}
-in the summation uses the same base address values {\tt irl!i} and
-{\tt iru!j}, so we could save 2 vector lookups per term.
-
-Also notice that for a given row {\tt i}, the expressions
-{\tt irl!i} and {\tt (fl i)} appear both in the definition of
-{\tt (l (i,j))} and in the array comprehension for {\tt new\_pl}.
-By abstracting these two expressions out of the definition of
-{\tt (l (i,j))} and computing them at the level of the array  
-comprehension,
-we not only share between these two parts of the program, we also
-ensure that these expressions are computed only once for a given row,
-instead of getting recomputed for each element in the row.
-
-Here is our final complete version of the $L*U$ factorization,
-giving the code for the lower triangle.  The code for the main
-diagonal and the upper triangle are similar.
-
-\begin{verbatim}
-    plu (n, old_pl, old_d, old_pu, irl, iru)  =
-        (n, new_pl, new_d, new_pu, irl, iru)
-    where
-        l (i,j) irli fli = s
-        where
-            kmin_l  = max fli (fu j)
-            iruj    = iru!j
-            l_exp k = new_pl!(irli + k) * new_pu!(k + iruj)
-            a_init  = old_pl!(irli + j)
-            s       = a_init - sum [ l_exp k | k <- [kmin_l..j-1] ]
-        new_pl  = array (bounds old_pl)
-                    [ (irli + j)  =  l (i,j) irli fli
-                        | i <- [2..n],
-                                irli <- [ irl!i ],
-                                fli  <- [ (fl i) ] ,
-                                j <- [fli+1..i-1] ]  ++
-                    [ (irli + j)  =  old_pl!(irli + j)
-                        | i <- [2..n],
-                                irli <- [ irl!i ],
-                                fli  <- [ (fl i) ],
-                                j <- [ fli ], fli < i ] ]
-        . . .
-\end{verbatim}
-
-An extension of the list comprehension that treats the nesting of
-generators and loop-invariant subexpressions more clearly and
-elegantly is discussed in \cite{ande89,ande89b}.
-
-If the compiler treats {\tt i} as an outer loop index and {\tt j} as
-an inner loop index, we have achieved the equivalent of lifting
-loop-invariant computations in Fortran.  There remain a few more
-opportunities for lifting common subexpressions in this program
-fragment, but we have taken all opportunities that lift
-loop-invariant subexpressions.
-
-\subsubsection{The $L*U*x = b$ solution phase.}
-
-We will discuss two versions of the backsolve phase, one version
-using the column-oriented {\tt U}, the other using the reorganized
-row-oriented {\tt U}.
-
-$A*x = L*U*x = b$ is equivalent to solving the lower triangular
-system $L*y = b$ , using the intermediate solution $y$ as the
-righthand side for solving the upper triangular system $U*x = y$.
-\begin{verbatim}
-    l!(1,1)*(y 1)                                       = b!1
-    l!(2,1)*(y 1) + l!(2,2)*(y 2)                       = b!2
-    . . .                                               . . .
-    l!(n,1)*(y 1) +       . . .       + l!(n,n)*(y n)   = b!n
-\end{verbatim}
-Recall that we are storing the inverse of diagonal elements under the
-name {\tt d!i = 1./l!(i,i)} for every {\tt i}.  For a typical row
-{\tt i}, this system of equations can be recast as the function:
-\begin{verbatim}
-    y_vec  =  array (1,n) [ i = y i  | i <- [1..n] ]
-    y i  =  s * d!i
-    where s  =  b!i - sum [ l!(i,j) * y_vec!j | j <- [1..i-1] ]
-\end{verbatim}
-
-Finally we solve the upper triangular system $U*x = y$, recalling again
-that $U$ is unit diagonal.
-The entire function, assuming the matrix {\tt lu} $= (L-D) + D^{-1} +
-(U-I)$ is in dense matrix format, and doing the appropriate substitutions
-for {\tt l!(i,j)}, {\tt d!i}, and {\tt u!(i,j)}:
-\begin{verbatim}
-    plub lu b  =  x_vec  where
-        y i    =  s * lu!(i,i)
-            where s  =  b!i - sum [ lu!(i,j) * y_vec!j | j <- [1..i-1] ]
-        x i    =  y_vec!i - sum [ lu!(i,j) * x_vec!j | j <- [i+1..n] ]
-        y_vec  =  array (1,n) [ i = y i  | i <- [1..n] ]
-        x_vec  =  array (1,n) [ i = x i  | i <- [1..n] ]
-\end{verbatim}
-
-Now let us stay with dense format, but incorporate the ``first
-nonzero" functions {\tt fl} and {\tt fu} to avoid multiplies and
-subtracts for terms in which the contribution weight {\tt l!(i,j)} or
-{\tt u!(i,j)} is outside the matrix envelope and therefore zero.  The
-change is trivial for the lower triangular system, since the summation
-is along a row.  For {\tt i <- [2..n]}, {\tt (fl i)} tells us the first
-nonzero column in row {\tt i}:
-\begin{verbatim}
-    y i  =  s * lu!(i,i)
-    where s  =  b!i - sum [ lu!(i,j) * y_vec!j | j <- [(fl i)..i-1]
-\end{verbatim}
-Otherwise {\tt y 1  =  b!1. }
-
-But for the upper triangle we have the problem that the summation is
-also running along a row, but {\tt fl} tells us the first nonzero in a  
-given
-column.  We cannot use it to give a bound on the summation for a row {\tt  
-i}
-the way we did for the lower triangular system.  We could instead use
-{\tt fl} as a predicate for each element of a row to see whether that  
-element
-falls outside the upper triangle's column-oriented envelope.
-\begin{verbatim}
-    x i  =  y_vec!i - sum [ lu!(i,j) * x_vec!j
-                            | j <- [i+1..n], (fu j) <= i ]
-    x_vec  =  array (1,n) [ i = x i  | i <- [1..n] ]
-\end{verbatim}
-Unfortunately, although we avoid an expensive floating point multiply and
-subtract for each zero {\tt u!(i,j)}, we still incur a predicate test for
-every element.  The upper triangular envelope may be of size $O(n)$,
-but testing {\em every} element for inclusion in the envelope forces us
-to perform $O(n^2)$ work.
-
-One approach at this stage is to switch to column-oriented view of
-$U$, which was convenient for the factorization phase, to a
-row-oriented view more appropriate to the backsolve phase.
-\cite{huda88f} gives a program that performs this column-oriented to
-row-oriented reorganization of $U$'s envelope representation.  The
-reorganization takes time proportional to the size of the upper
-triangle's row-oriented envelope.  For matrices in which the maximum
-size of any row envelope is independent of matrix size $n$, this time
-is $O(n)$.
-
-Another solution is to imitate the Fortran solution, which walks through
-$U$ column by column, performing successive updates on the {\tt x}
-vector as each {\tt x!j} becomes available.  Keeping for now the dense
-representation of {\tt lu}, we can transform the definition of
-{\tt xvec} given above to this form:
-\begin{verbatim}
-    x_vec  =  j_loop n y_vec
-    j_loop j x_vec  =
-        if j < 1
-            then x_vec
-            else j_loop (j-1)
-                    (array (1,n)
-                        [ i = x_vec!i | i <- [1..fuj-1] ] ++
-                        [ i = x_vec!i - lu(i,j) * x_vec!j
-                                      | i <- [fuj..j-1] ] ++
-                        [ i = x_vec!i | i <- [j..n] ])
-                    where fuj = fu j
-\end{verbatim}
-For each iteration of {\tt j} we define a new monolithic array, but we can
-easily transform this version to loop over {\tt i} using an
-element-at-a-time incremental update function:
-{\tt (upd x\_vec i new\_value)}.
-Or we can define a function {\tt bigupdate} that has the same
-semantics as the {\tt array} expression above, but it is only
-necessary to specify the elements that are {\em different} from
-{\tt x\_vec}.
-\begin{verbatim}
-  . . .
-  else j_loop (j-1)
-              (bigupdate x_vec
-                 [ i = x_vec!i - lu(i,j) * x_vec!j | i <- [(fu j)..j-1] ])
-\end{verbatim}
-A {\tt bigupdate} function could perform an in-place update if the
-compiler determines this is safe (see \cite{ande89,ande89b}).
-The semantics of {\tt bigupdate} takes a middle ground between the
-{\tt upd} function's incremental view of functional arrays and the
-{\tt array} constructor's monolithic view.
-
-We finally convert our program to use a envelope format version 
-by making the appropriate substitutions to convert references
-to {\tt lu} into references to {\tt pl, pu}, and {\tt d}.
-Here is the final complete version of the $L*U*x = b$ solver.
-
-\begin{verbatim}
-    plub (n, pl, d, pu, irl, iru) b  =  x_vec
-    where
-        fl i   =  i - 1 + irl!(i-1) - irl!i
-        y i    =  s * d!i  where
-                s  =  b!i - sum [ pl!(irl!i + j) * y_vec!j
-                                       | j <- [(fl i)..i-1] ]
-        y_vec  =  array (1,n) [ 1 = b!1 * d!1 ] ++ 
-                              [ i  =  y i  |  i <- [2..n] ]
-
-        fu j   =  j - 1 + iru!(j-1) - iru!j
-        x_vec  =  j_loop n y_vec
-        j_loop j x_vec  =
-            if j < 1
-                then x_vec
-                else j_loop (j-1)
-                        (bigupdate x_vec
-                            [ i = x_vec!i - pu!(i + iru!j) * x_vec!j
-                                          | i <- [(fu j)..j-1] ] )
-\end{verbatim}
-
-Andy Sherman's version of {\tt plub} also deals with reordering
-the unknowns to achieve a narrower envelope.
-The linear system $A*x = b$ may have been poorly organized for the
-envelope representation, and the equivalent system $ P*A*P^{-1}*P*x
-= P*b $ may require a smaller envelope to store $A$ and its
-factorization.  The permutation matrix $P$ reorganizes the rows
-($P^{-1}$ the columns) using reverse Cuthill-McKee (RCM) 
-heuristic to minimize the envelope size.
-
-Sherman's version of {\tt plub}
-assumes that the $LU$-factorized envelope-format matrix is in RCM order,
-whereas input vector {\tt b} and result vector {\tt x} are in the original
-order.  If we have a vector {\tt iord} representing the permutation $P$
-mapping the original number {\tt i} to RCM number {\tt iord!i},
-then the change to {\tt plub} is trivial, and is left as an exercise.
-
-\section{Acknowledgements}
-
-We wish to thank Joe Fasel at Los Alamos for comments on various parts
-of this document, as well as for providing us with his solution to the
-doctors' office problem.  Also thanks to Los Alamos and Lawrence
-Livermore National Laboratories for their sponsorship of the Salishan
-High-Speed Computing Conference.
-
-\bibliographystyle{alpha}
-\bibliography{//alta/yale/hudak/bib/new,//alta/yale/hudak/bib/old}
-
-\end{document}
diff --git a/spectral/salishan/id.tex b/spectral/salishan/id.tex
deleted file mode 100644 (file)
index c13f125..0000000
+++ /dev/null
@@ -1,6010 +0,0 @@
-
-The files needed to assemble the Id chapter of the Salishan Problems
-book are:
-
-Latex files:
-
-   7 salishan.tex
-  14 intro.tex
-   6 hamming.tex
-  12 paraffins.tex
-  29 doctor.tex
-  16 skyline.tex
-   3 salishan.bib
-
-Postscript files for illustrations:
-
-  22 hamming_ext_3-to-23_5000.ps
-  17 paraffins_until_15.ps
-  20 doctor_det_20_4.ps
-  20 doctor_non-det_20_4.ps
-  19 skyline-1.ps
-  14 skyline-2.ps
-  15 skyline-3.ps
-  14 skyline-4.ps
-  20 skyline-lubksb_sky_50.ps
-  12 skyline-ludcmp_sky_50.ps
-  22 skyline-solve_sky_50.ps
-
-On our installation, I assemble it as follows:
-
-    Run "latex salishan"     (starts with "salishan.tex", which
-                              uses \input{} to get all the other tex files)
-    Run "bibtex salishan"    (uses "salishan.bib")
-    Run "latex salishan" again to resolve cross-refs.
-
-This produces a file "salishan.dvi" (and the other usual LaTeX output
-files).  The tex files refer to the postscript figures by using the
-\special TeX command.  For example, at the point where the figure in
-"skyline-0.ps" should be included, we have the command:
-
-    \special{psfile=/where/skyline-0.ps hoffset=-72 voffset=-45}}
-
-where /where/ is the Unix directory holding the ps file.  Latex just
-passes these commands on to the DVI file (i.e., Latex does not merge
-in the figures).  Finally, I print the file by saying:
-
-    lpr -d salishan.dvi
-
-At some point, the DVI file gets converted to postscript and the
-postscript figures are merged in, and the result sent to the printer.
-
-I am very uncertain about the portability of this last step (merging
-in the figures).
-
-----------------------------------------------------------------
-
-% Salishan problems
-% Rishiyur S. Nikhil
-% October, 1989 thru January 1990
-
-\documentstyle[12pt]{article}
-
-% HORIZONTAL MARGINS
-% Left margin 1.5 inch (0.5 + 1)
-\setlength{\oddsidemargin}{0.5in}
-% Text width 6 inch (so right margin 1 inch).
-\setlength{\textwidth}{6in}
-% ----------------
-% VERTICAL MARGINS
-% Top margin 1.5 inch (0.5 + 1)
-\setlength{\topmargin}{0.5in}
-% Head height 0.25 inch (where page headers go)
-\setlength{\headheight}{0.25in}
-% Head separation 0.25 inch (between header and top line of text)
-\setlength{\headsep}{0.25in}
-% Text height 8 inch (so bottom margin 1 in)
-\setlength{\textheight}{8in}
-% ----------------
-% PARAGRAPH INDENTATION
-\setlength{\parindent}{0in}
-% SPACE BETWEEN PARAGRAPHS
-\setlength{\parskip}{\medskipamount}
-% ----------------
-% STRUTS
-% HORIZONTAL STRUT.  One argument (width).
-\newcommand{\hstrut}[1]{\hspace*{#1}}
-% VERTICAL STRUT. Two arguments (offset from baseline, height).
-\newcommand{\vstrut}[2]{\rule[#1]{0in}{#2}}
-% ----------------
-% HORIZONTAL LINE ACROSS PAGE:
-\newcommand{\hdivider}{\noindent\mbox{}\hrulefill\mbox{}} 
-% ----------------
-% EMPTY BOXES OF VARIOUS WIDTHS, FOR INDENTATION
-\newcommand{\hm}{\hspace*{1em}}
-\newcommand{\hmm}{\hspace*{2em}}
-\newcommand{\hmmm}{\hspace*{3em}}
-\newcommand{\hmmmm}{\hspace*{4em}}
-% ----------------
-% VARIOUS CONVENIENT WIDTHS RELATIVE TO THE TEXT WIDTH, FOR BOXES.
-\newlength{\hlessmm}
-\setlength{\hlessmm}{\textwidth}
-\addtolength{\hlessmm}{-2em}
-
-\newlength{\hlessmmmm}
-\setlength{\hlessmmmm}{\textwidth}
-\addtolength{\hlessmmmm}{-4em}
-% ----------------
-% ``TIGHTLIST'' ENVIRONMENT (no para space betwee items, small indent)
-\newenvironment{tightlist}%
-{\begin{list}{$\bullet$}{%
-    \setlength{\topsep}{0in}
-    \setlength{\partopsep}{0in}
-    \setlength{\itemsep}{0in}
-    \setlength{\parsep}{0in}
-    \setlength{\leftmargin}{1.5em}
-    \setlength{\rightmargin}{0in}
-    \setlength{\itemindent}{0in}
-}
-}%
-{\end{list}
-}
-% ----------------
-% ITALICISE WORDS
-\newcommand{\ie}{{\em i.e.,\/}}
-\newcommand{\eg}{{\em e.g.,\/}}
-\newcommand{\etc}{{\em etc.\/}}
-\newcommand{\via}{{\em via\/}}
-\newcommand{\vs}{{\em vs.\/}}
-% ----------------
-% CODE FONT (e.g. {\cf x := 0}).
-\newcommand{\cf}{\footnotesize\tt}
-% ----------------
-% KEYWORDS
-\newcommand{\kw}[1]{{\bf #1}}
-% ----------------------------------------------------------------
-% ID CODE DISPLAYS.
-% Id code displays are enclosed between \bid and \eid.
-% Most characters are taken verbatim, in typewriter font,
-% Except:
-%  Commands are still available (beginning with \)
-%    but use ` and ' instead of { and }
-%  Math mode is still available (beginning with $)
-%    but use ~ and ! for ^ and _
-
-\outer\def\beginid{%
-  \begin{list}{$\bullet$}{%
-    \setlength{\topsep}{0in}
-    \setlength{\partopsep}{0in}
-    \setlength{\itemsep}{0in}
-    \setlength{\parsep}{0in}
-    \setlength{\leftmargin}{0in}
-    \setlength{\rightmargin}{0in}
-    \setlength{\itemindent}{0in}
-  }\item[]
-%  \catcode`\{=12
-%  \catcode`\}=12
-  \catcode`\&=12
-  \catcode`\#=12
-  \catcode`\%=12
-%  \catcode`\~=12
-%  \catcode`\_=12
-  \catcode`\^=12
-%  \catcode`\~=7
-  \catcode`\!=7      % superscript
-%  \catcode`\'=2
-%  \catcode`\`=1
-  \obeyspaces
-  \obeylines \footnotesize\tt}
-
-\outer\def\endid{%
-  \end{list}
-  }
-
-{\obeyspaces\gdef {\ }}
-
-% ----------------
-% The same as \beginid and \endid, except in environment form because otherwise
-% I can't include it in fboxes (Latex complains).
-
-\newenvironment{idenv}{%
-  \begin{list}{$\bullet$}{%
-    \setlength{\topsep}{0in}
-    \setlength{\partopsep}{0in}
-    \setlength{\itemsep}{0in}
-    \setlength{\parsep}{0in}
-    \setlength{\leftmargin}{0in}
-    \setlength{\rightmargin}{0in}
-    \setlength{\itemindent}{0in}
-  }\item[]
-  \catcode`\&=12
-  \catcode`\#=12
-  \catcode`\%=12
-  \catcode`\^=12
-  \catcode`\!=7      % superscript
-  \obeyspaces
-  \obeylines \footnotesize\tt}{%
-  \end{list}}
-
-% ----------------
-% ILLUSTRATIONS
-% This command should specify a directory for ps files for illustrations.
-\def\psfileprefix{/jj/nikhil/docs/89-10-salishan/}
-\def\illustration#1#2{
-\vbox to #2{\vfill\special{psfile=\psfileprefix#1.ps hoffset=-72 voffset=-45}}} 
-
-% \illuswidth is used to set up boxes around illustrations.
-\newlength{\illuswidth}
-\setlength{\illuswidth}{\textwidth}
-\addtolength{\illuswidth}{-7pt}
-
-% ----------------------------------------------------------------
-% ----------------------------------------------------------------
-% HERE BEGINS THE DOCUMENT
-
-% \includeonly{doctor}
-
-\begin{document}
-
-{\Large\bf Id: a language with implicit parallelism}
-
-Rishiyur S. Nikhil {\it and\/} Arvind
-
-Massachusetts Institute of Technology
-
-{\footnotesize Laboratory for Computer Science, 545 Technology Square, Cambridge, MA 02139, USA} \\
-{\footnotesize e-mail: \hmm {\tt nikhil@lcs.mit.edu} \hmm {\it and\/} \hmm {\tt arvind@lcs.mit.edu}}
-
-% ----------------
-
-% Introduction
-
-\input{intro}
-
-% ----------------
-
-% Hamming's problem, extended
-
-\input{hamming}
-
-% ----------------
-
-% The Paraffins Problem
-
-\input{paraffins}
-
-% ----------------
-
-% A doctor's office
-
-\input{doctor}
-
-% ----------------
-
-% Skyline matrix solver
-
-\input{skyline}
-
-% ----------------
-
-\vspace{1in}
-
-{\bf Acknowledgements}
-
-{\footnotesize
-
-Steve Heller was mainly responsible for our solution to the paraffins
-problem, developed in 1988.
-
-The non-deterministic doctor's office program was developed with much
-discussion with Paul Barth, who is also responsible for the
-implementation of managers and performing our test run.
-
-Although our skyline matrix solver uses Crout's method, we have
-learned a lot from previous work on linear equation solvers that used
-Gauss elimination.  K.  Ekanadham of IBM Research developed elegant Id
-programs for dense matrices, and Javed Aslam, Christopher Colby and
-Ken Steele developed Id programs for sparse matrices.
-
-This report describes research done at the Laboratory for Computer
-Science of the Massachusetts Institute of Technology.  Funding for the
-Laboratory is provided in part by the Advanced Research Projects
-Agency of the Department of Defense under the Office of Naval Research
-contract N00014-89-J-1988.
-
-}
-
-
-\bibliographystyle{unsrt}
-\bibliography{salishan}
-
-% ----------------
-
-\end{document}
-
-% ----------------------------------------------------------------
-% Testing figures
-
- \begin{figure}[htbp]
- \fbox{%
-   \parbox%
-     {\illuswidth}
-     {\illustration{solve_sky_50_composite}{2.4 true in}
-      \caption{%
-         \label{solve_sky_50_composite}
-         Solve skyline example size 50
-              }
-     }}
- \end{figure}
-
-\end{document}
-
-----------------------------------------------------------------
-
-% Salishan problems
-% Rishiyur S. Nikhil
-% October, 1989 thru January 1990
-
-% Introduction
-
-\section{Introduction}
-
-Id is a parallel programming language developed in the Computation
-Structures Group at MIT's Laboratory for Computer Science.\footnote{A
-first version of Id appeared in 1978.  Since 1985, it underwent a
-series of revisions during which it was variously called Id/83s, Id86,
-Id Noveau, \etc, finally reverting to just ``Id'' again.
-
- } In developing Id, we have three major goals.
-
-{\em High level\/}: at least as expressive as modern functional
-languages and Lisp.  Parallelism in Id is implicit--- the user does
-not have to manage partitioning, scheduling and synchronization.
-
-{\em General purpose\/}: suitable for both ``scientific'' and
-``symbolic'' computation.  Id has efficient arrays and floating-point
-operations, as well as recursive data structures (\eg\ lists) in an
-automatically managed heap.
-
-{\em High performance\/}: Our aim is for an Id program compiled for a
-dataflow machine to achieve at least as much absolute performance as
-its FORTRAN counterpart on a von Neumann machine built with comparable
-technology.\footnote{However, Id is in no way specific to dataflow
-machines.}
-
-Id is a layered language \cite{Nikhil88c,Nikhil90a}, with layer 0
-representing the cleanest semantics and layer 2 representing the most
-expressive power.  Layer 0 is purely functional, and is similar to
-other modern functional languages like Miranda and Haskell, \ie\ it
-has higher-order functions, non-strict semantics, polymorphic types
-with static type-checking by inference, algebraic types with
-pattern-matching, list comprehensions, and user-defined abstract data
-types.  Id's ``array comprehensions'' are fairly unique.
-
-Layer 1 adds ``I-structures'' to layer 0. These permit a limited form
-of assignment.  One can allocate data structures with empty slots,
-assign values to these slots, and read values from these slots.  A
-slot can be assigned a value no more than once.  Reading a value from
-a slot is automatically blocked until it has been assigned a value.
-This addition sacrifices the referential transparency of layer 0, but retains
-determinacy, since the value read from a slot does not depend on the time
-that the program attempts to read it.  The loss of referential transparency
-implies a certain loss in the ability to transform programs (\eg\ for proving
-correctness, for program optimization, \etc); however, the benefits are:
- \begin{tightlist}
-
-    \item Certain programs that involve excessive copying when written
-    functionally can now be written more efficiently.
-
-    \item Certain programs that must be written recursively when written
-    functionally can now be written using loops, \ie\ tail-recursively.
-
- \end{tightlist}
-Most of the programs in this chapter do not use I-structures
-explicitly (a small use is made in the Doctor's office section).
-However, the Id compiler uses I-structures extensively to implement
-all data structures, including those from layer 0.
-
-Layers 0 and 1 are purely determinate, \ie\ answers depend only on
-inputs.  Layer 2 introduces non-determinism by adding ``Managers'' to
-layer 1, for those applications that need it, such as shared-resource
-problems and operating systems.  An example will be seen in the
-Doctor's office section.
-
-It is possible to instruct the Id compiler to only accept programs
-restricted to layer 0 or layer 1, since each layer involves new
-syntactic constructs.
-
-\subsection{A brief introduction to the language}
-
-Id programs are built up from {\em expressions\/}.  In addition to
-standard infix operators like ``{\cf +}'', Id uses juxtaposition to
-indicate function application:
-
-\beginid
-f $e_1$ ... $e_n$
-\endid
-
-Functions are defined using {\cf def}:
-
-\beginid
-def clip top y = if (y > top) then top else y ;
-\endid
-
-Functions are curried, and application associates to the left, so that
-the expression:
-
-\beginid
-clip 5
-\endid
-
-denotes a function of one argument that clips its argument to 5.
-
-Data structures in Id are defined using {\em algebraic types\/}.
-However, some data structures are so useful that they are pre-defined
-with special notation.  An {\em n-tuple\/} may be constructed by
-listing $n$ expressions separated by commas.  Here is a 2-tuple:
-
-\beginid
-(a+b),(a-b)
-\endid
-
-A list is either empty ({\cf Nil}), or constructed using the infix
-``cons'' operator ({\cf $e_{1}$:$e_{2}$}).  Destructuring of lists
-(testing for emptiness, acessing the head and tail) is usually done
-using pattern-matching--- function on lists are defined in several
-clauses:
-
-\beginid
-def length Nil    = 0                         % {\it for empty lists}
- |  length (x:xs) = 1 + length xs ;           % {\it for non-empty lists}
-\endid
-
- The clauses must have disjoint patterns.  The second clause binds
-{\cf x} and {\cf xs} to the head and tail, respectively, of the
-non-empty argument list.
-
-A local scope may be created using a {\em block\/}. Blocks may be
-nested, with standard lexical scoping.  The bindings in a block can
-include function definitions:
-
-\beginid
-% {\it integrate function $f(x)$ from $a$ to $b$}
-def integrate f a b = \{ delta = 0.0001 ;
-                        def iter x s = if x > b then
-                                         s
-                                       else
-                                         iter (x + delta) (s + f x) ;
-                      In
-                        delta * (iter a 0) \} ;
-\endid
-
- The block contains one ordinary binding and one function binding.
-The value returned by the block (and the {\cf integrate} function) is
-the value of the expression following the {\cf In} keyword.  Note that
-{\cf integrate} is higher-order--- its first argument is itself a
-function.
-
-Although recursion subsumes iteration, Id also has {\cf while}-and
-{\cf for}-loop constructs.
-
-Like other functional languages, Id also has {\em list
-comprehensions\/}.  The following expression creates all pairs $(x,y)$
-such that $y \leq x$ and $x^2+y^2 \leq 25$ (all pixels in first octant
-within radius 5):
-
-\beginid
-\{: (x,y) || x <- 0 to 5 & y <- 0 to x when x*x + y*y <= 25 \}
-\endid
-
-Terms like ``\mbox{\cf x <- 0 to 5}'' are called {\em generators\/}
-and terms like ``{\cf when ...}'' are called {\em filters\/}.
-Generators and filters are scoped from left to right, \ie\ they can
-use identifiers bound in generators to their left.
-
-Id also has arrays, which are constructed using {\em array
-comprehensions\/}.  This expression denotes an identity matrix of size
-$n \times n$:
-
-\beginid
-\{matrix (1,n),(1,n)
-| [i,j] = 0 || i <- 2 to n & j <- 1 to (i-1)          % {\it below diagonal}
-| [i,i] = 1 || i <- 1 to n                            % {\it diagonal}
-| [i,j] = 0 || j <- 2 to n & i <- 1 to (j-1) \}        % {\it above diagonal}
-\endid
-
-In general, arrays can have arbitrary lower and upper bounds, and they
-can be queried at run time using the {\cf bounds} function.  The array
-contents in the example are specified in three regions--- below, on
-and above the diagonal, respectively.  The specifications must be
-disjoint--- a run time error will catch multiple definitions.  The
-generator syntax is identical to that in list comprehensions.
-
-For efficiency reasons, we distinguish vectors, matrices,
-3-dimensional arrays, \etc\ on the basis of type.
-
-\subsection{Non-strict, but not lazy}
-
-Lazy and eager evaluation are {\em not\/} synonymous with strict and
-non-strict semantics, respectively (even though this confusion is
-widespread in the literature).  The former terms are concerned with
-operational semantics (what interpreters do), while the latter terms
-are concerned with denotational semantics (declarative meanings of
-programs).  Non-strictness may be achieved by both lazy as well as
-eager (parallel) evaluators.
-
-When a lazy evaluator encounters an application {\cf f(arg)}, {\em
-no\/} computational resources are devoted to {\cf arg}.  Instead, {\cf
-arg} is packaged into a closure and passed to {\cf f}.  If {\cf f}
-ever requires the value of {\cf arg}, the evaluator then devotes all
-its computational resources to it, \ie\ it invokes the closure.
-
-On the other hand, Id achieves non-strictness with a parallel, eager
-evaluator.  Computational resources are shared amongst {\cf f} and
-{\cf arg}, \ie\ {\cf f} is invoked in parallel with {\cf arg}, passing
-only a place-holder for {\cf arg} to {\cf f}.  If {\cf f} ever
-requires the value of {\cf arg}, it blocks on the place-holder.  If
-{\cf f} ignores its argument, it simply discards the place-holder.
-Eager evaluation is thus speculative.
-
-However, not all computation in Id is speculative.  In particular, the
-arms of conditionals (more-generally, {\cf case} expressions) are not
-evaluated speculatively.  After the predicate has determined which arm
-is required, only that arm is evaluated.  This is how we control
-recursion, and our experience has been that with this control, in
-almost all cases, the potential waste of resources due to speculative
-argument evaluation is not a problem.
-
-The advantages of Id's eager evaluation are that (a) we avoid the
-overhead of building a closure for {\cf arg} and later invoking it,
-and (b) the computation of {\cf arg} is begun before it is really
-demanded, thus increasing the parallelism and shortening the critical
-path.  Consider the following Id expression representing an array of
-the first 20 Fibonacci numbers:
-
-\beginid
-\{ fibs = \{array (1,20)
-         | [i] = 1                   || i <- 1 to 2
-         | [i] = fibs[i-1]+fibs[i-2] || i <- 3 to 20\}
-In
-  fibs \}
-\endid
-
-Such a recursive array definition is only possible in non-strict
-languages like Id, Haskell, and Miranda, and is not possible in strict
-languages like Lisp and ML.  However, in this example, there is no
-need at all for lazy evaluation.  In fact, the overhead of building
-closures for all the array components is likely to far outstrip the
-cost of computing the array in the first place.
-
-The disadvantage of eager evaluation is that if a value is never
-demanded, the resources allocated to compute it are wasted.  The
-extreme case of this occurs when the value represents an infinite
-structure.  We handle these cases by special annotations that request
-lazy evaluation.  These will be described in our solution to the
-Hamming problem.
-
-An approach currenly being investigated by various researchers is to
-start with lazy evaluation as the default, and to use {\em strictness
-analysis\/} to predict where it is safe to evaluate things eagerly.
-However, it is too early to judge its effectiveness on large programs
-with data structures and higher-order functions.  Further, it will
-have no effect on our {\cf fibs} program above, which {\em requires\/}
-non-strictness.  It appears that in lazy languages, it will be
-necessary to have annotations to suggest ``eager'' evaluation.
-
-We note in passing that the Haskell language definition only requires
-non-strict semantics--- it takes no position on lazy or eager
-evaluation.  This is appropriate, for it leaves implementors with some
-latitude for experimentation.
-
-\subsection{Implementations of Id}
-Our efforts have concentrated on compilation of Id for dataflow
-machines which, to date, have been emulated in software.  A complete
-programming environment for Id, called ``Id World'', is available
-under license from MIT for a small fee.  It contains a compiler that
-translates Id programs into the machine code for the MIT Tagged-Token
-Dataflow Architecture (TTDA).  In addition, Id World contains GITA, an
-emulator for the TTDA.  Extensive instrumentation in GITA permits the
-experimenter to collect and plot various statistics such as
-parallelism profiles, instruction counts, instruction mixes, resource
-usage profiles, \etc\
-
-We are currently building a real dataflow machine called Monsoon.  An
-early single-processor prototype of Monsoon has been running compiled
-Id since October 1988.  In collaboration with Motorola, we are
-building new, multi-processor Monsoon machines which are expected to
-be available in the summer of 1989.  We aim to retain the current Id
-World interface for Monsoon, so that programs can be developed today
-for Monsoon.
-
-We have recently begun to study compilation of Id for other sequential
-and parallel machines as well, which will increase its availability
-and value to other researchers.
-
-\subsection{Our test runs: parallelism profiles, instruction counts and critical path lengths}
-
-All the Id programs in this chapter were run on GITA, and we present
-their parallelism profiles, instruction counts, and critical path
-lengths.  The emulator was run in ``idealized'' mode, \ie\ with the
-following assumptions:
-
- \begin{tightlist}
-
-\item
-All instructions take one time unit to execute.
-
-\item
-Each instruction executes as soon as its input data are ready (\ie\
-immediately after all its predecessor instructions in the dataflow
-graph have executed).
-
-\item
-It takes zero time to communicate data from an instruction to its
-successor in the dataflow graph.
-
- \end{tightlist}
-
-The {\em parallelism profile\/} is a plot of the number of instructions
-executed at each time step.  The {\em total instruction count\/}, therefore,
-is the area under the curve.  The {\em critical path length\/} is that time
-step after which no more instructions execute.
-
-While this ``idealized'' mode is admittedly unrealistic, it is very
-useful in showing what is the maximum parallelism available under some
-algorithm.  As some of the problems in this chapter demonstrate, the
-parallelism of some algorithms is not at all obvious.
-----------------------------------------------------------------
-
-% Salishan problems
-% Rishiyur S. Nikhil
-% October, 1989 thru January 1990
-
-\section{Hamming's problem, extended}
-
-Our program is shown in Figure \ref{hamming-program}, with {\cf
-hamming\_ext} as the top-level function.
-
-\begin{figure}[htbp]
- \hdivider
-\begin{idenv}
-def hamming\_ext primes n =
-    \{ def f xs p = \{  h = merge\_2 (mapmult p (1:h)) xs
-                   In
-                      h \} ;
-      hs = 1: foldl\_list f Nil primes ;
-    In
-      until\_n n hs \} ;
-\null
-def mapmult p Nil    = Nil
- |  mapmult p (x:xs) = (p*x):#(mapmult p xs);
-\null
-def merge\_2 Nil    Nil    = Nil
- |  merge\_2 (x:xs) Nil    = (x:xs)
- |  merge\_2 Nil    (y:ys) = (y:ys)
- |  merge\_2 (x:xs) (y:ys) = if (x < y) then
-                              x :# merge\_2 xs (y:ys)
-                            else if (x > y) then
-                              y :# merge\_2 (x:xs) ys
-                            else
-                              x :# merge\_2 xs ys ;
-\null
-def until\_n n Nil    = Nil
- |  until\_n n (x:xs) = if (x <= n) then
-                         x:(until\_n n xs)
-                       else
-                         Nil ;
-\end{idenv}
- \caption{%
-    \label{hamming-program}
-    Id program for the extended Hamming problem.
-         }
- \hdivider
-\end{figure}
-
-In order to explain the solution, we begin with a solution for the
-original (simpler) Hamming problem, where the primes are limited to 2,
-3 and 5.  It is a direct implementation of the observation that if $h$
-is in the result $hs$, then $2h$, $3h$ and $5h$ are also in $hs$:
-
- \beginid
-def hamming n =
-    \{ hs = 1 : merge\_2 (mapmult 2 hs)
-                       (merge\_2 (mapmult 3 hs)
-                                (mapmult 5 hs)) ;
-     In
-       until\_n n hs \} ;
- \endid
-
-Here, {\cf hs} is a stream, \ie\ a potentially infinite list.  {\cf
-Mapmult} takes an integer $p$ and a stream $x_1,x_2,\ldots$ and
-produces the stream $px_1,px_2,\ldots$.  {\cf Merge\_2}, takes two
-streams in ascending order and merges them into a new stream in
-ascending order, removing duplicates. {\cf Until\_n} produces the
-prefix of a stream containing just those numbers that are $\leq n$.
-These functions are shown in Figure \ref{hamming-program}
-
-In each of these functions, we are dealing with potentially infinite
-lists.  Thus, we use the ``lazy-tail'' list-constructor ``{\cf :\#}''
-to override Id's default eager evaluation.  It is also possible to
-delay the head, or both the head and the tail, by using the
-constructors ``{\cf \#:}'' and ``{\cf \#:\#}'', respectively.  The
-annotations are only in the constructor--- component selection is
-identical for delayed and non-delayed components.
-
-The above program is inefficient because the three streams that are
-merged together contain several duplicates (\eg\ 2*3, 3*2) that are
-then removed during the merge.  Here is a new solution that avoids
-building duplicates in the first place:
-
- \beginid
-def hamming n =
-    \{ hs = 1: \{  s1 = mapmult 2 (1:s1) ;
-                 s2 = merge\_2 (mapmult 3 (1:s2)) s1 ;
-                 s3 = merge\_2 (mapmult 5 (1:s3)) s2 ;
-               In
-                 s3 \} ;
-    In
-      until\_n n hs \} ;
- \endid
-
-Here, {\cf s1} contains all the powers of 2, {\cf s2} merges in all
-products with all powers of 3, and so on.
-
-Finally, we can generalize our last solution so that, instead of
-working with just the primes 2, 3, and 5, it works with a list of
-primes.  This is shown in the function {\cf hamming\_ext} in Figure
-\ref{hamming-program}.  The function {\cf foldl\_list} performs
-the nested merge of our previous solution, \ie\
-
- \beginid
-foldl\_list f Nil (p1:...:pN:Nil) $\Rightarrow$ (f ( ... (f (f Nil p1) p2) ... ) pN)
- \endid
-
-It is available as a library function in Id, but it can also be
-defined as:
-
- \beginid
-def foldl\_list f z Nil    = z
- |  foldl\_list f z (x:xs) = foldl\_list f (f z x) xs ;
- \endid
-
-\subsection{A test run}
-
-We ran the following program on GITA, our dataflow emulator:
-
-\beginid
-hamming\_ext (3:5:7:11:13:17:19:23:Nil) 5000
-\endid
-
-with the following output:
-\beginid
-
-(1 3 5 7 9 11 13 15 17 19 21 23 25 27 33 35 39 45 49 51 55 57 63 65 69
-75 77 81 85 91 95 99 105 115 117 119 121 125 133 135 143 147 153 161
-165 169 171 175 187 189 195 207 209 221 225 231 243 245 247 253 255
-273 275 285 289 297 299 315 323 325 343 345 351 357 361 363 375 385
-391 399 405 425 429 437 441 455 459 475 483 495 507 513 525 529 539
-561 567 575 585 595 605 621 625 627 637 663 665 675 693 715 729 735
-741 759 765 805 819 825 833 845 847 855 867 875 891 897 931 935 945
-969 975 1001 1029 1035 1045 1053 1071 1083 1089 1105 1125 1127 1155
-1173 1183 1197 1215 1225 1235 1265 1275 1287 1309 1311 1323 1331 1365
-1375 1377 1425 1445 1449 1463 1485 1495 1521 1539 1547 1573 1575 1587
-1615 1617 1625 1683 1701 1715 1725 1729 1755 1771 1785 1805 1815 1859
-1863 1875 1881 1911 1925 1955 1989 1995 2023 2025 2057 2079 2093 2125
-2145 2185 2187 2197 2205 2223 2261 2275 2277 2295 2299 2375 2401 2415
-2431 2457 2475 2499 2527 2535 2541 2565 2601 2625 2645 2673 2691 2695
-2717 2737 2783 2793 2805 2835 2873 2875 2907 2925 2975 3003 3025 3059
-3087 3105 3125 3135 3159 3179 3185 3211 3213 3249 3267 3289 3315 3325
-3375 3381 3465 3519 3549 3553 3575 3591 3645 3675 3703 3705 3757 3773
-3795 3825 3861 3887 3927 3933 3969 3971 3993 4025 4095 4125 4131 4165
-4199 4225 4235 4275 4301 4335 4347 4375 4389 4455 4459 4485 4563 4617
-4641 4655 4675 4693 4719 4725 4761 4807 4845 4851 4875 4913)
-
-\endid
-
-which is not in Id syntax because GITA, written in Lisp, simply
-prints out the Lisp value of the result.  The parallelism profile
-generated is shown in Figure \ref{hamming_ext_3-to-23_5000}.
-
- \begin{figure}[htbp]
- \fbox{%
-   \parbox%
-     {\illuswidth}
-     {\illustration{hamming_ext_3-to-23_5000}{1.78 true in}
-      \caption{%
-         \label{hamming_ext_3-to-23_5000}
-         Parallelism profile for {\tt (hamming\_ext (3:5:...:19:23:Nil) 5000)}
-              }
-     }}
- \end{figure}
-----------------------------------------------------------------
-
-% Salishan problems
-% Rishiyur S. Nikhil
-% October, 1989 thru January 1990
-
-% The Paraffins Problem
-
-\section{The paraffins problem}
-
-Turner's original solution \cite{Turner81} was written in the language
-KRC.  It can be transcribed practically verbatim into Id, since the
-functional core of Id is similar to KRC (including list
-comprehensions), and Id shares the same non-strict semantics as KRC.
-However, that solution is quite inefficient, because it generates many
-duplicates only to be filtered out later.  In \cite{Arvind88b}, we
-showed an efficient program that avoids generating duplicates in the
-first place, using the canonical tree-enumeration techniques described
-in \cite{Knuth73} (and discovered independently by S.K.  Heller, our
-co-author in \cite{Arvind88b}).  That solution is repeated here, and
-is shown in two parts: Figure \ref{radicals-program} shows the code
-for the sub-problem of generating radicals, and Figure
-\ref{paraffins-program} shows the generation of paraffins, with
-top-level function {\cf paraffins\_until}.  For more details,
-including a discussion of the development of the solution, please see
-\cite{Arvind88b}.
-
-\begin{figure}[htbp]
- \hdivider
-\begin{idenv}
-type radical = H | C radical radical radical ;
-\null
-def 3\_partitions m =
-        \{: (i,j,k) || i <- 0 to floor (m/3)
-                    & j <- i to floor ((m-i)/2)
-                    & k  =  m - (i + j) \} ;
-\null
-def remainders Nil    = Nil
- |  remainders (r:rs) = (r:rs) : (remainders rs) ;
-\null
-def radical\_generator n =
-    \{ radicals = \{array (0,n)
-                 | [0] = H:nil
-                 | [j] = rads\_of\_size\_n radicals j || j <- 1 to n\}
-    In
-      radicals\} ;
-\null
-def rads\_of\_size\_n radicals n =
-    \{: C ri rj rk || (i,j,k) <- 3\_partitions (n-1)
-                   & ri:ris <- remainders (radicals[i])
-                   & rj:rjs <- remainders (if (i == j) then ri:ris
-                                           else radicals[j])
-                   & rk     <- if (j == k) then rj:rjs
-                               else radicals[k] \} ;
-\end{idenv}
- \caption{%
-    \label{radicals-program}
-    Id program for the generating radicals for the paraffins problem.
-         }
- \hdivider
-\end{figure}
-
-\subsection{Radicals}
-
-A radical is a paraffin with a single hydrogen atom removed, \ie\ a
-molecule with formula C$_i$H$_{2i+1}$.  The structure of such
-molecules can be recursively described as either
-
-\begin{tightlist}
- \item a Hydrogen atom, or
- \item a Carbon atom attached to three other radicals
-\end{tightlist}
-
-This is expressed in {\cf radical} type-declaration in Figure
-\ref{radicals-program}. It consists of two disjuncts with
-constructors {\cf H} and {\cf C}, respectively.  In the latter case,
-there are four components, each of which is itself of type {\cf
-radical}.
-
-By way of illustration, here are some more examples of algebraic type
-declarations.  The type of booleans can be declared:
-\beginid
-type bool = False | True ;
-\endid
-The type of binary trees with integers in the nodes can be declared:
-\beginid
-type tree = Leaf | Node int tree tree ;
-\endid
-And, the type of lists can be declared:
-\beginid
-type (list *0) = Nil | Cons *0 (list *0) ;
-\endid
-The list type is {\em polymorphic\/} because it is parameterized by a
-type variable {\cf *0}, so that we can have lists of integers, lists
-of booleans, lists of lists of integer-to-integer functions, \etc\
-
-\subsection{Generating radicals}
-
-Suppose we wish to generate all radicals of size $n$.  For $n > 0$,
-the radical will have one carbon as its ``root'' carbon, and three
-sub-radicals of collective size $n-1$.  Thus, we need to partition
-$n-1$ into three sizes in order to generate the sub-radicals.
-However, if we use all possible 3-partitions of $n-1$, we will
-generate many duplicate radicals because the partition $(i,j,k)$ is
-equivalent to $(i,k,j)$, $(j,i,k)$, and so on.  We can avoid this by
-insisting that $i \leq j \leq k$.  The function {\cf 3\_partitions} is
-a function to generate a list of all three partitions of $m$ ($= n-1$)
-in this canonical order.
-
-The generation of radicals of size $n$ can defined recursively.  When
-$n=0$, there is only one such radical--- a lone hydrogen atom.  When
-$n>0$, we construct all canonical 3-partitions $(i,j,k)$ of $n-1$; for
-each such partition, we generate, recursively, all radicals {\cf ri}
-of size $i$, all radicals {\cf rj} of size $j$ and all radicals {\cf
-rk} of size $k$, and construct the new radical \mbox{\cf (C ri rj rk)}.
-Here is the function:
-
- \beginid
-def rads\_of\_size\_n n = 
-    if (n == 0) then
-      H:Nil
-    else
-      \{: C ri rj rk || (i,j,k) <- 3\_partitions (n-1)
-                     & ri <- rads\_of\_size\_n i
-                     & rj <- rads\_of\_size\_n j when (le? ri rj)
-                     & rk <- rads\_of\_size\_n k when (le? rj rk) \} ;
- \endid
-where {\cf le?} is some function that checks that its two radical
-arguments are in canonical order.  The first {\cf when} clause takes
-care of the following situation: when $i=j$, since {\cf ri} and {\cf
-rj} range over all possible pairs of radicals of size $i$, they may
-not be in canonical order--- the {\cf when} clause filters out these
-pairs.  Similarly, the second {\cf when} clause filters out duplicates
-when $j=k$.
-
-We can avoid this generation-of-duplicates-and-filtering as follows.
-For each $i$, let {\cf ri} range over $ri_1,ri_2, \ldots$.  Then, when
-$i=j$ and, when {\cf ri} is, say, $ri_4$, we make {\cf r2} range over
-$ri_4, ri_5, \ldots$.  Thus, for each element of the list, we would
-like to have access not only to that element, but also to the
-remainder of that list.
-
-In particular, we need a function that, given $ri_1, ri_2, ri_3,
-\ldots$, produces the list of lists:
-\[
-(ri_1,ri_2,ri_3,ri_4,ri_5,\ldots),(ri_2,ri_3,ri_4,ri_5,\ldots),(ri_3,ri_4,ri_5,\ldots),\ldots
-\]
-
-The function that performs this is called {\cf remainders} (Figure
-\ref{radicals-program}).
-
-Now, we can improve our {\cf rads\_of\_size\_n} function:
- \beginid
-def rads\_of\_size\_n n =
-    \{: C ri rj rk || (i,j,k) <- 3\_partitions (n-1)
-                   & ri:ris <- remainders (rads\_of\_size\_n i)
-                   & rj:rjs <- remainders (if (i == j) then ri:ris
-                                           else rads\_of\_size\_n j)
-                   & rk     <- if (j == k) then rj:rjs
-                               else rads\_of\_size\_n k \} ;
- \endid
-
-However, there is still a major inefficiency in this function.  It has
-the classical Fibonacci recursion, because to compute radicals of,
-say, size 3, we compute radicals of size 0, 1, and 2, but to compute
-radicals of size 2, we compute radicals of size 0 and 1, and so on.
-In other words, we recompute radicals of each size too often.
-
-We use a standard trick--- use an array to cache, at index $n$, the
-list of radicals of size $n$, and just look up this array each time we
-need radicals of size $n$.  In Figure \ref{radicals-program}, {\cf
-radical\_generator} is the function that constructs this array, using
-{\cf rads\_of\_size\_n} to compute each component.  And, {\cf
-rads\_of\_size\_n} itself uses this array to find radicals of size
-$<n$.
-
-\subsection{Paraffins from radicals}
-
-\hfill {\footnotesize\it Or, Molotov cocktails?}
-
-\bigskip
-
-Please refer to Figure \ref{paraffins-program}.
-
-\begin{figure}[htbp]
- \hdivider
-\begin{idenv}
-type paraffin = BCP radical radical | CCP radical radical radical radical ;
-\null
-def BCP\_generator radicals n =
-        if (odd? n) then
-          Nil
-        else
-          \{: BCP r1 r2 || r1:r1s <- remainders (radicals[floor (n/2)])
-                        & r2 <- r1:r1s \} ;
-\null
-def 4\_partitions m =
-        \{: (i,j,k,l) || i <- 0  to floor (m/4)
-                      & j <- i to floor ((m-i)/3)
-                      & k <-    (max j (ceiling (m/2-i-j)))
-                             to (floor ((m-i-j)/2))
-                      & l =  m - (i+j+k) \} ;
-\null
-def CCP\_generator radicals n =
-        \{: CCP ri rj rk rl || (i,j,k,l) <- 4\_partitions (n-1) 
-                            & ri:ris <- remainders (radicals[i])
-                            & rj:rjs <- remainders (if i==j then ri:ris
-                                                    else radicals[j])
-                            & rk:rks <- remainders (if j==k then rj:rjs
-                                                    else radicals[k])  
-                            & rl <- if (k==l) then rk:rks
-                                    else radicals[l] \} ;
-\null
-def paraffins\_until n =
-    \{ radicals = radical\_generator (floor (n/2)) ;
-    In
-      \{array (1,n)
-      | [j] = (BCP\_generator radicals j),
-              (CCP\_generator radicals j)   || j <- 1 to n\}\} ;
-\end{idenv}
- \caption{%
-    \label{paraffins-program}
-    Id program for the paraffins problem.
-         }
- \hdivider
-\end{figure}
-
-In order to define a canonical form for paraffins, we observe that
-every paraffin of size $n$ has either
-
-\begin{tightlist}
-
-\item a unique {\em bond center\/}, \ie\  a bond with $\frac{n}{2}$-sized
-radicals on its two sides, or
-
-\item a unique {\em carbon center\/}, \ie\ a carbon attached to 4 radicals,
-each of size $< \frac{n}{2}$.
-
-\end{tightlist}
-
-This is expressed in the {\cf paraffin} type-declaration in Figure
-\ref{paraffins-program}.   We can then define our canonical representation as either \mbox{\cf (BCP r1
-r2)} where \mbox{\cf r1 $\leq$ r2}, or \mbox{\cf (CCP r1 r2 r3 r4)}
-where \mbox{\cf r1 $\leq$ r2 $\leq$ r3 $\leq$ r4}.
-
-Bond-centered paraffins can be enumerated using the function {\cf
-BCP\_generator}, whose first argument should be the array of radicals
-defined in the previous section, \ie\ from the list of radicals of
-size $\frac{n}{2}$, we draw all pairs {\cf r1} and {\cf r2} such that
-{\cf r2} does not precede {\cf r1} in the list.
-
-To enumerate carbon-centered paraffins in canonical order, we follow a
-strategy similar to the one used to produce radicals.  For a paraffin
-of size $n$, one carbon is the center, so we find all canonical
-4-partitions $(i,j,k,l)$ of $n-1$, representing the sizes of the four
-attached radicals (\ie\ $i \leq j \leq k \leq l$).  For each of these
-4-partitions, we take all the radicals {\cf ri}, {\cf rj}, {\cf rk}
-and {\cf rl} of sizes $i$, $j$, $k$, and $l$, respectively.  We use
-the same ``remainders'' trick to take care of avoiding duplicates when
-$i=j$, $j=k$ and $k=l$.  Using these radicals, we form the paraffins
-\mbox{\cf (CCP r1 r2 r3 r4)}.
-
-Finally, our top-level function {\cf paraffins\_until} takes a numeric
-argument $n$ and generates an array of size $n$ such that the $n$'th
-index contains a pair of lists--- a list of all bond-centered
-paraffins of size $n$ and a list of all carbon-centered paraffins of
-size $n$. Each list is in canonical order.  It would be easy to
-flatten this into a single list, if desired.
-
-\subsection{A test run}
-
-The parallelism profile for {\cf (paraffins\_until 15)} is shown in
-Figure \ref{paraffins_until_15}.  The number of paraffins containing
-$n$ carbons, for $n=1,2,\cdots,15$ are 1, 1, 1, 2, 3, 5, 9, 18, 35,
-75, 159, 355, 802, 1858 and 4347, respectively.  The parallelism of
-this program is not at all obvious from the algorithm.
-
-% Elapsed time: 165.55 secs
-
- \begin{figure}[htbp]
- \fbox{%
-   \parbox%
-     {\illuswidth}
-     {\illustration{paraffins_until_15}{1.87 true in}
-      \caption{%
-         \label{paraffins_until_15}
-         Parallelism profile for {\tt (paraffins\_until 15)}
-              }
-     }}
- \end{figure}
-----------------------------------------------------------------
-
-% Salishan problems
-% Rishiyur S. Nikhil
-% October, 1989 thru January 1990
-
-% A Doctor's Office
-
-\section{A doctor's office}
-
-It is not clear which of the following programs is requested in the
-problem statement.
-
-\begin{tightlist}
-
-\item A {\em determinate\/} simulation in which the non-determinism
-of the real world is modelled by an oracle that is a parameter to the
-program; or
-
-\item A program that is itself non-deterministic.
-
-\end{tightlist}
-
-If the intent is really to simulate a doctor's office, then the former
-program makes more sense, because it is repeatable and we can control
-the choices made by the oracle.  However, if the intent is to see how
-non-determinism is handled by the programming language (for example to
-evaluate its suitability for operating systems code), then the latter
-program makes more sense.  Accordingly, we have developed solutions
-for both interpretations.
-
-We begin by discussing how (pseudo-)random numbers may be generated
-and used in Id.
-
-\subsection{Random numbers}
-
-\label{random-numbers}
-
-Here is a function for the linear congruence method of generating
-random numbers\footnote{
- See \cite{Knuth73b} for an extensive discussion.
- }.
- Given a seed {\cf X}, it returns a random
-number {\cf r} in the range 0 to 1 and a new seed {\cf X'}.
-
-
- \beginid
-def rand\_fn X =  \{ a = 25173 ; c = 13849 ; m = 65536 ;
-                   r = X / (m - 1) ;
-                   X' = mod (a*X + c) m ;
-                 In
-                   r,X' \} ;
-\endid
-
-{\em Streams of random numbers\/}: We can use this function, for
-example, to produce a stream of random numbers, given an initial seed
-{\cf X0}:
-
-\beginid
-def mk\_random\_stream X0 = \{ def mk\_rs X = \{ r,X' = rand\_fn X
-                                          In
-                                            r:# mk\_rs X'\} ;
-                          In
-                            mk\_rs X0 \} ;
-\endid
-
-Here, we have used the ``lazy-tail'' list constructor ``{\cf :\#}'' to
-delay the construction of the tail of the stream, since we are likely
-to use only a small prefix.  For more efficiency, it is possible to
-mix regular and lazy list constructors so that, for example, the
-stream is delayed at every 100'th element.
-
-{\em Picking a random element of a list\/}: Given a random number {\cf
-r} in the range 0 to 1, we can use the following function to pick a
-random member of a list.  {\cf Pick\_random} not only returns the
-random element, but also the other members of the list:
-
-\beginid
-def pick\_random r xs =
-    \{ n = round (r * (length xs - 1)) ;
-      def separate j (x:xs) = if (j == n) then
-                                x,xs
-                              else
-                                \{ x',xs' = separate (j+1) xs
-                                In
-                                  x',(x:xs') \}
-    In
-      separate 0 xs \} ;
-\endid
-
-{\em Picking a random event\/}: Suppose we want to choose one of three
-possible events with probabilities 1\%, 54\% and 45\% respectively.
-Here is a function we can use:
-
- \beginid
-def choose\_event r = if (r <= 0.01) then 0
-                     else if (r <= 0.55) then 1
-                     else 2 ;
- \endid
-where, again, {\cf r} is a random number in the range 0 to 1.
-
-\subsection{A determinate simulator for the doctor's office}
-
-Our determinate solution is shown in Figure \ref{doctor-det-program}.
-
-\begin{figure}[htbp]
- \hdivider
-\begin{idenv}
-def sick\_event r (wellps, consults, waitps, waitds, hist1, hist2, hist3) =
-    if (wellps == Nil) then
-      (wellps, consults, waitps, waitds, hist1, hist2, hist3)
-    else
-      \{ (p,wellps') = pick\_random r wellps
-      In
-        if (waitds == Nil) then
-          (wellps', consults, (waitps ++ p:Nil), waitds, p:hist1, hist2, hist3)
-        else
-          \{ (d:waitds') = waitds
-          In
-            (wellps', (p,d):consults, waitps, waitds',
-             p:hist1, (p,d):hist2, hist3)\}\} ;
-\null
-def cure\_event r (wellps, consults, waitps, waitds, hist1, hist2, hist3) =
-    if (consults == Nil) then
-       (wellps, consults, waitps, waitds, hist1, hist2, hist3)
-    else
-       \{ (p,d),consults' = pick\_random r consults
-       In
-         if (waitps == Nil) then
-           (p:wellps, consults', waitps, waitds ++ d:Nil, hist1, hist2, p:hist3)
-         else
-           \{ (p':waitps') = waitps
-           In
-             (p:wellps, (p',d):consults, waitps', waitds,
-              hist1, (p',d):hist2, p:hist3) \}\} ;
-\null
-def process randoms (wellps, consults, waitps, waitds, hist1, hist2, hist3) =
-    \{  r1:r2:randoms' = randoms ;
-       e = choose\_event r1
-    In
-       \{case e of
-          0 = reverse hist1, reverse hist2, reverse hist3
-       |  1 = process randoms'
-                      (sick\_event r2
-                                   (wellps, consults, waitps, waitds,
-                                    hist1, hist2, hist3))
-       |  2 = process randoms'
-                      (cure\_event r2
-                                   (wellps, consults, waitps, waitds,
-                                    hist1, hist2, hist3)) \} \};
-\null
-def simulate randoms patients doctors =
-    process randoms
-            (patients, Nil, Nil, doctors, Nil, Nil, Nil) ;
-\end{idenv}
- \caption{%
-    \label{doctor-det-program}
-    Determinate program for the doctor's office problem.
-         }
- \hdivider
-\end{figure}
-
-The state of the system at any time can be modelled by seven items:
-\begin{tightlist}
-
-\item {\cf wellps}, a collection of well patients.
-
-\item {\cf waitps}, a queue of sick patients waiting for doctors.
-
-\item {\cf waitds}, a queue of doctors waiting for sick patients.
-
-\item {\cf consults}, a collection of patient-doctor pairs (in consultation).
-
-\item Three ``histories'': {\cf hist1}, a list of patients as they fall
-sick, {\cf hist2}, a list of patient-doctor pairs as they go into
-consultation, and {\cf hist3}, a list of patients as they get cured.
-
-\end{tightlist}
-
-There are only two kinds of events that drive the system:
-
-\begin{itemize}
-
-\item A {\cf sick\_event}: Some well patient {\cf p} falls sick.  Of course,
-this can only happen if {\cf wellps} is non-empty.
-
-{\em Effects\/}: We use {\cf r}, a random number in the range 0 to 1
-to choose which patient falls sick.  If a doctor {\cf d} is available
-({\cf waitds} is non-empty), {\cf p} and {\cf d} go into consultation
-({\cf consults}); otherwise, {\cf p} joins the queue {\cf waitps}.
-
-We record that {\cf p} fell sick in {\cf hist1}.  If a consultation
-{\cf (p,d)} began, we record it in {\cf hist2}.
-
-\item A {\cf cure\_event}:  Some consultation terminates (doctor {\cf d} cures patient {\cf p}).
-Of course, this can only happen if {\cf consults} is non-empty.
-
-{\em Effects\/}: We use {\cf r}, a random number in the
-range 0 to 1 to choose which patient-doctor consultation terminates.
-The patient {\cf p} rejoins the well patients ({\cf
-wellps}).  If there is a waiting patient {\cf p'} in {\cf waitps}, the
-doctor {\cf d} goes into consultation with {\cf p'}; otherwise, the
-doctor rejoins the queue {\cf waitds}.
-
-We record that {\cf p} was cured in {\cf hist3}.  If a consultation
-{\cf (p',d)} began, we record it in {\cf hist2}.
-
-\end{itemize}
-
-These state transitions are encoded in the functions {\cf sick\_event}
-and {\cf cure\_event} (all the state components are modelled as
-lists).  Each function takes a random number and a state and produces
-a new state.  The sick-patients and free-doctors queues are
-represented as lists, where the first element of the list represents
-the head of the queue.  Thus, enqueuing is performed using ``{\cf
-++}'', the built-in infix list-appending operator.  It should be
-observed that the histories are constructed in reverse order.  We
-shall reverse them at the end of the simulation.
-
-{\cf Simulate} is the top-level driver.  It takes a stream of random
-numbers (in the range 0 to 1), the initial list of patients and the
-initial list of doctors, and calls {\cf process}, passing in empty
-lists for {\cf consults}, {\cf waitps}, {\cf hist1}, {\cf hist2} and
-{\cf hist3}.
-
-The function {\cf process} chooses an action randomly: stop, a
-sick-event, or a cure-event.  In the first case, it reverses the
-histories and returns them as the final result.  In the latter two
-cases, it applies the appropriate state-transition function, and
-recursively calls {\cf process} on the new state.
-
-\subsubsection{A test run}
-
-We ran the following test program:
-
-\begin{minipage}{\textwidth}
-\begin{idenv}
-def test (patients,doctors,seed) =
-    \{ randoms = mk\_random\_stream seed ;
-      (ps,pds,cs) = simulate randoms patients doctors ;
-    In
-      (length ps),(length pds),(length cs),ps,pds,cs \} ;
-\end{idenv}
-\end{minipage}
-
-supplying a list of 20 patients ({\cf "P0"} through {\cf "P19"}), a
-list of 4 doctors ({\cf "D0"} through {\cf "D3"}) and an initial
-random seed.  The first three components of {\cf test}'s resulting
-6-tuple showed that during the simulation, patients fell sick 92
-times, doctors were paired with patients 76 times, and doctors cured
-patients 72 times.
-
-It is clear from the parallelism profile shown in Figure
-\ref{doctor_det_20_4} that the program does not have much parallelism.
-
- \begin{figure}[htbp]
- \fbox{%
-   \parbox%
-     {\illuswidth}
-     {\illustration{doctor_det_20_4}{1.8 true in}
-      \caption{%
-         \label{doctor_det_20_4}
-         Parallelism profile for determinate Doctor program (20 patients, 4 doctors)
-              }
-     }}
- \end{figure}
-
-\subsection{Non-deterministic programming in Id}
-
-As mentioned in the introduction, Id is a layered language. The first
-two layers (functional, and I-structures) retain determinacy---
-results depend only on inputs.  However, in operating systems code and
-other applications, we may {\em require\/} non-deterministic behavior.
-The doctor's office problem may be viewed as an abstraction of the
-resource manager problem in operating systems.  The doctors may be
-regarded as resources that are demanded and held non-deterministically
-by client processes (patients).\footnote{We take this asymmetric view
-only because of the wording of the problem statement.  If doctors went
-away for random periods between seeing patients, then we would have
-symmetry.  We would model ``consultations'' as the resource that is
-demanded by two kinds of clients (doctors and patients).}
-
-To express such computations, Id has another layer called
-``managers''.  Managers are a relatively recent addition to Id.
-Although the technical ideas behind managers are quite well
-understood, the notation is still experimental and is not yet part of
-the Id manual.  We have a prototype implementation, and a test run of
-the program described in the next section was executed on this
-implementation.
-
-There have been various attempts to introduce non-determinism into
-functional languages.  Perhaps the most common approach is to use a
-special non-deterministic {\cf merge} operation: given two stream
-inputs, {\cf merge} produces an interleaved output, where the
-interleaving is non-deterministic.  In an actual implementation, the
-interleaving is typically done in the temporal order in which elements
-of the input streams become available.  In order to distribute results
-from a resource manager to requestors, it is necessary to: tag the
-requests in the input-streams with unique stream-identifiers before
-merging them non-deterministically; carry these tags along with the
-resource-allocation computation so that they identify which result is
-meant for which requestor, and split and distribute the output stream
-according to these tags.
-
-This approach to non-determinism is highly unsatisfactory for several
-reasons. First, it is very difficult to use when the number of streams
-to be merged (number of users of a resource) is not manifest, leading
-to a ``spaghetti'' of tagging and plumbing.  Second, it is very
-difficult to follow a static type discipline, because all the
-different kinds of requests to a resource manager, each with different
-arguments, must be merged into a single homogeneously typed stream.
-
-A more elegant attempt is described in \cite{Arvind84}, from where we
-have inherited the term ``managers''.  A manager was specified as a
-stream-to-stream function, and the tagging and non-deterministic merge
-at the entry to the manager was hidden with clever notation and clever
-implementation.  While eliminating the ``plumbing'' problem of
-explicit non-deterministic merges, the static-type-checking issue
-still remained.
-
-The Id {\cf manager} construct not only solves all these problems, but
-also lends itself to very efficient implementation.
-
-Non-determinism and side-effects are closely related--- each can be
-used to simulate the other.  However, managers are an attempt to
-facilitate disciplined use of side-effects in the presence of
-parallelism.  The {\cf manager} construct declares a new, abstract
-type, \ie\ objects of this new type may only be manipulated by the set
-of interface procedures (called {\em handlers\/}) specified in the
-manager construct.  However, unlike ordinary abstract types, these
-objects have {\em state\/} that may be updated by the handlers.  Thus,
-each handler not only specifies a result to be returned, but also
-possibly a new state for any objects given to it as arguments.
-Manager semantics guarantee that the state transitions on an object
-appear to be atomic.
-
-We begin with a simple random-number generator manager that uses {\cf
-rand\_fn}, the linear congruence method from Section
-\ref{random-numbers}:
-
-\begin{minipage}{\textwidth}
-\begin{idenv}
-manager rand\_supplier = Cons\_cell float
-\{
-    def make\_rand\_supplier seed = Cons\_cell seed ;
-\null
-    def next\_rand (Cons\_cell seed) = \{ r, seed' = rand\_fn seed ;
-                                       new seed = seed'
-                                     In
-                                       r \} ;
-\} ;
-\end{idenv}
-\end{minipage}
-
-The first line is similar to an algebraic type definition.  It defines
-a new type, {\cf rand\_supplier}, and specifies the constructors for
-this type--- here, just one unary constructor {\cf Cons\_cell}.  By
-using the keyword {\cf manager} instead of {\cf type}, we indicate (a)
-that it is updateable and (b) that the constructor {\cf Cons\_cell} is
-visible only in the statements that follow between braces, thus making
-{\cf rand\_supplier} an {\em abstract type\/} with respect to the rest
-of the program.  The statements in braces consist of two handlers.
-The first is a constructor of new {\cf rand\_supplier} objects.  Given
-a seed, it creates a new object containing the seed, and returns the
-new object as its result.  This object is first-class, \ie\ in the
-rest of the program, it can be an argument or result of a procedure,
-it can be stored in data structures, \etc\ However, because {\cf
-Cons\_cell} is not visible outside the manager declaration, the object
-is {\em opaque\/} to the rest of the program.  To
-do anything that requires manipulation of the internal state (reading
-it or updating it) it has to be passed to one of the handlers, which
-are the only procedures that can examine and update the internal
-state.
-
-The second handler, when applied to a {\cf rand\_supplier} object,
-applies {\cf rand\_fn} to the old seed value to produce a random
-number {\cf r} and a new seed {\cf seed'}.  The update to the state is
-specified by the binding that uses the \mbox{\cf new} keyword.  The
-procedure returns the value {\cf r}.
-
-Because a {\cf rand\_supplier} object is a first-class object, there
-may be many references to it.  Thus, there may be many concurrent
-attempts to apply {\cf next\_rand} to it.  Managers guarantee that
-such concurrent accesses are {\em serializable\/}, even though the
-user has not mentioned any locking or synchronization.  The
-reading-out of the seed, application of {\cf rand\_fn} to it, and
-storing of the new seed is performed as an {\em atomic\/} action.
-Thus, two concurent accessors can never see the same seed.
-
-In general, a manager object can contain multiple components, and each
-handler may read and update more than one component.  Atomicity is
-still guaranteed, \ie\ another concurrent execution of a handler on
-the same object cannot read intermediate states.  These properties of
-a managed object make it easy to establish and maintain invariants on
-the state of the object by ensuring that the {\em each\/} state update
-by a handler maintains the invariant.
-
-Thus, managers are akin to Hoare's {\em monitors\/} \cite{Hoare74}.
-However, there is an important difference that has far-reaching
-consequences.  Within a handler, the new value of each state component
-can be specified at most once.  This allows handlers to be {\em
-non-strict\/}, \ie\ the state update (critical section) and the
-return-value computation can be decoupled.
-
-One consequence of this decoupling is increased concurrency.  The
-return-value computation does not have to be in the critical section,
-so that the critical section may be released before the return-value
-is computed.  Conversely, the critical section does not have to be in
-the critical path of the caller of a handler, so that a result may be
-returned to the caller before the critical section is completed.
-
-A second major consequence is that a manager can have complete control
-over the scheduling of concurrent accessors (events, {\cf wait}'s and
-{\cf signal}'s, in monitor terminology).  To achieve this, we use a
-feature in Id called ``I-structures''.  I-structures are dynamically
-allocated and, at first, appear to be ordinary updateable cells.  For
-example, the function {\cf make\_cell} allocates a cell, the procedure
-{\cf put\_cell} stores a value in the cell, and the procedure {\cf
-get\_cell} reads a value from the cell.  However, I-structure
-semantics make them different from updateable cells.  In particular, a
-value may be put into a cell {\em at most once\/}, and {\cf get\_cell}
-automatically blocks on an empty cell until a value has been written
-there.  An error occurs if an attempt is made to put a value twice
-into a cell.
-
-We illustrate this device with a manager for a {\em queue\/} of
-strings.  A small modification of this example will be used later in
-our Doctor's office solution.  We wish to use handlers {\cf enq} and
-{\cf deq} to enqueue and dequeue strings from the queue, respectively.
-A fundamental difference from, say, the {\cf rand\_supplier} manager
-is that the queue manager may have to respond to requests {\em out of
-order\/}.  In particular, if one process attempts {\cf deq} on an
-empty queue, its response must be deferred until another process
-performs an {\cf enq} operation.  We call such managers {\em
-scheduling\/} managers, as opposed to {\em simple\/} managers
-like {\cf rand\_supplier}.
-
-The code for the queue manager is shown below.
-
-\beginid
-manager queue = Cons\_queue (list S)             % {\it queued strings\/}
-                           (list (cell S))      % {\it waiting dequeuers\/}
-\{
-    def make\_queue xs = Cons\_queue xs Nil ;
-\null
-    def enq (Cons\_queue xs cs) x =              % x {\it is a string\/}
-        \{case cs of
-           Nil     = \{ new xs = xs ++ (x:Nil)   % {\it Enter\/} x {\it at end of queue\/}
-                     In
-                       Ok \}
-         | (c:cs') = \{ new cs = cs' ;
-                       call put\_cell c x        % {\it Send\/} x {\it to the dequeueing\/}
-                     In                         % {\it process that is blocked on\/} c
-                       Ok \} \} ;
-\null
-    def deq (Cons\_queue xs cs) =
-        \{case xs of
-           Nil     = \{ c = make\_cell \_ ;        % {\it Make a cell to block on\/}
-                       new cs = cs ++ (c:Nil)   % {\it Enter it at end of dequeuers\/}
-                     In
-                       get\_cell c  \}            % {\it Block, trying to read the cell\/}
-         | (x:xs') = \{ new xs = xs' ;
-                     In
-                       x \} \} ;
-\} ;
-\endid
-
-In the first line, we indicate that the internal representation of a
-queue object is built with the {\cf Cons\_queue} constructor, and
-contains two components--- a list of strings (``{\cf S}'' is the type
-for strings) and a list of cells that can contain strings (cells are
-typed objects).  The first list represents the strings that are
-currently enqueued.  The second list represents the cells on which
-dequeuing processes are waiting.  Note that both lists will never
-simultaneously be non-empty, \ie\ either there can be strings enqueued
-or there can be waiting processes, but not both.
-
-The constructor {\cf make\_queue} takes an initial list of strings
-{\cf xs}, builds a queue object containing these strings and an empty
-list of waiting cells, and returns this object.
-
-The {\cf enq} handler checks if there are any waiting processes (cells
-{\cf cs}). If not, it attaches the given string {\cf x} at the end of
-the list of enqueued strings (using the built-in list-concatenation
-operator ``{\cf ++}'').  If there is a waiting process (blocked on
-cell {\cf c}), it puts the string {\cf x} into the cell (thereby
-unblocking the waiting process and giving it the string), and updates
-the list of cells to be the rest of the cells {\cf cs'}.  In either
-case, the constant {\cf Ok} is returned as a result to the enqueueing
-process.  The keyword {\cf call} is used to indicate that the
-expression following it is executed purely for its side-effect (in
-this case, the call to {\cf put\_cell}).
-
-The {\cf deq} handler checks if there are any enqueued strings {\cf
-xs}.  If not, it allocates an empty cell {\cf c}, appends it to the
-list of waiting cells, and blocks trying to read the cell {\cf c}.
-Because of the non-strict evaluation mechanism, the blocking takes
-place {\em outside\/} the critical section, \ie\ the state update can
-take place and the object is then available for other concurrent
-processes, one of which will presumably unblock this process by
-writing a value into {\cf c}.  Note that we use ``{\cf \_}'' as a
-``don't care'' argument to {\cf make\_cell}.
-
-If there is an enqueued string {\cf x} available to a {\cf deq}
-request, it is returned as a result, and it updates the state to
-contain the remaining enqueued strings {\cf xs'}.
-
-Thus, the semantics of managers are such that it allows us to choose
-the order in which it responds to requests.  This is in contrast to
-the {\em implicit\/} scheduling imposed by the {\cf wait} and {\cf
-signal} constructs in Hoare's monitors.
-
-\subsection{A non-deterministic simulator for the doctor's office}
-
->From the queue example, it is but a small step to the
-non-deterministic doctor's office simulator.  The code is shown in
-Figure \ref{doctor-non-det-program}.  The top-level function is {\cf
-simulate}, which takes a random-number supply (an object as discussed
-above), a list of patients, a list of doctors, and a number {\cf
-max\_iter} which determines the duration of the simulation.  It
-creates a doctor's office initialized with all doctors free (to be
-described below).  The \mbox{\cf for p}-loop, being a parallel loop,
-simulates all patients simultaneously.
-
-\begin{figure}[htbp]
- \hdivider
-\begin{idenv}
-def simulate rand\_supply patients doctors max\_iter =
-    \{ office = make\_office doctors ;
-      \{for p <- patients do                        % {\it For each patient,\/}
-        \{for j <- 1 to max\_iter do
-                delay (next\_rand rand\_supply) ;    % {\it Be healthy for random time\/}
-          THEN  d = get\_doctor office p ;
-          THEN  delay (next\_rand rand\_supply) ;    % {\it Consult for random time\/}
-          THEN  call put\_doctor office p d
-          THEN \}\} ;
-    THEN
-    In
-      histories office \} ;
-\null
-manager office = Make\_office (list S)                        % {\it waiting doctors\/}
-                             (list (S,cell S))               % {\it waiting patients\/}
-                             (list S) (list (S,S)) (list S)  % {\it histories\/}
-\{
-    def make\_office doctors = Make\_office doctors Nil Nil Nil Nil Nil ;
-\null
-    def get\_doctor (ds,sps,h1,h2,h3) p =
-        \{case ds of
-           (d:ds') = \{ new ds = ds' ;                     % {\it Doctor\/} d {\em available\/}
-                       new h2 = (p,d):h2 ;  new h1 = p:h1
-                     In
-                       d \}
-         | Nil     = \{ c = make\_cell \_ ;                  % {\it No doctor available\/}
-                       new sps = sps ++ (p,c):Nil ;
-                       new h1 = p:h1
-                     In
-                       get\_cell c \}\} ;
-\null
-    def put\_doctor (ds,sps,h1,h2,h3) p d =
-        \{case sps of
-           ((p',c):sps') = \{ new sps = sps' ;             % {\it Patient} p' {\it waiting\/}
-                             call put\_cell c d ;          % {\it Send doctor to him\/}
-                             new h2 = (p',d):h2 ;  new h3 = p:h3
-                           In
-                             Ok \}
-         | Nil           = \{ new ds = ds ++ d:Nil ;       % {\it No patient waiting\/}
-                             new h3 = p:h3
-                           In
-                             Ok \}\} ;
-\null
-    def histories (ds,sps,h1,h2,h3) = (reverse h1), (reverse h2), (reverse h3) ;
-\} ;
-\end{idenv}
- \caption{%
-    \label{doctor-non-det-program}
-    Non-deterministic program for the doctor's office problem.
-         }
- \hdivider
-\end{figure}
-
-The \mbox{\cf for j}-loop simulates the life of each patient.  Until
-the end of the simulation\footnote{ We have modeled the duration of
-the simulation as a fixed number of iterations, since the problem
-statement does not specify anything. Another possibility would be to
-consult a real-time clock (which would, of course, be implemented as a
-manager object.)}, patient {\cf p} repeatedly behaves like this.  He
-is healthy for a random duration (using the procedure {\cf delay}) and
-then falls sick, at which point he asks the office for a doctor.  When
-he gets a doctor, he consults with him for a random duration (second
-{\cf delay}) and is then cured.  He then returns the doctor to the
-office and repeats the cycle.
-
-The {\cf THEN} separator is used to force a sequencing where otherwise
-things would have been done in parallel.  When all the loops have
-terminated (ensured by the last {\cf THEN}), we extract and return the
-histories maintained in the office.
-
-The manager definition for the doctors' {\cf office} is shown next in
-Figure \ref{doctor-non-det-program}.  Like the {\cf queue} manager, it
-also maintains two queues: a queue of free doctors and a queue of
-waiting sick patients; in addition, it maintains the three history
-lists (patients falling sick, patients-and-doctors going into
-consultation and patients cured).  We model a doctor by a string (the
-doctor's name).  A waiting patient is modeled by a string (the
-patient's name) and a cell that represents the place where a doctor
-should be put when one becomes available.
-
-The constructor {\cf make\_office} simply creates a new {\cf office}
-object with the free-doctors component initialized to the given list
-of doctors, and all other components empty.
-
-The handler {\cf get\_doctor} checks if there is any free doctor
-{\cf d}.  If so, he is removed from the free list {\cf ds}; {\cf p}
-and {\cf d} are entered in history {\cf h2}, and {\cf d} is returned
-to the requestor.  If there is no free doctor, then the response is
-deferred using a cell {\cf c} which is appended with {\cf p} into the
-list of waiting sick patients.  In either case, {\cf p} is entered in
-history {\cf h1}.
-
-The handler {\cf put\_doctor} checks if there is any waiting sick
-patient {\cf p'}.  If so, {\cf p'} is taken off the waiting list, the
-released doctor is immediately sent to {\cf p'} \via\ the associated
-cell {\cf c}, and {\cf p',d} is entered in {\cf h2}.  If there are no
-waiting patients, the doctor is returned to the free doctors list.  In
-either case, the cured patient {\cf p} is entered in history {\cf h3},
-and an acknowledgment ({\cf Ok}) is returned to him.
-
-Finally, the handler {\cf histories\/} returns the three histories,
-first reversing them because they were collected in the reverse order.
-
-\subsubsection{A test run}
-
-The code we ran was a small variation on the code shown in Figure
-\ref{doctor-non-det-program} because our experimental implementation
-is based on an older notation.  The parallelism profile is shown in
-Figure \ref{doctor_non-det_20_4}.
-
- \begin{figure}[htbp]
- \fbox{%
-   \parbox%
-     {\illuswidth}
-     {\illustration{doctor_non-det_20_4}{1.9 true in}
-      \caption{%
-         \label{doctor_non-det_20_4}
-         Parallelism profile for non-determinate Doctor program (20 patients, 4 doctors)
-              }
-     }}
- \end{figure}
-----------------------------------------------------------------
-
-% Salishan problems
-% Rishiyur S. Nikhil
-% October, 1989 thru January 1990
-
-% Skyline matrix solver.
-
-\section{Skyline matrix solver}
-
-\subsection{Crout's method for LU decomposition}
-
-To solve the system of linear equations {\bf Ax = b},
-our approach is based on LU decomposition using Crout's method, as
-described in \cite{Press86}.  We first show a solution for dense
-matrices, and then modify it for skyline matrices.  Suppose we express
-{\bf A} as the product of some {\bf L} and {\bf U}, which are lower
-and upper triangular matrices, respectively:
-
- \[
-{\bf L} \cdot {\bf U} = {\bf A}
- \]
-For example ($n=4$):
-
-{\footnotesize
-
- \[
-\left[
-\begin{array}{cccc}
-l_{11} &    0   &   0    &   0    \\
-l_{21} & l_{22} &   0    &   0    \\
-l_{31} & l_{32} & l_{43} &   0    \\
-l_{41} & l_{42} & l_{43} & l_{44}
-\end{array}
-\right]
-% ----------------
-\cdot
-% ----------------
-\left[
-\begin{array}{cccc}
-u_{11} & u_{12} & u_{13} & u_{14} \\
-   0   & u_{22} & u_{23} & u_{24} \\
-   0   &   0    & u_{33} & u_{34} \\
-   0   &   0    &   0    & u_{44}
-\end{array}
-\right]
-% ----------------
-=
-% ----------------
-\left[
-\begin{array}{cccc}
-a_{11} & a_{12} & a_{13} & a_{14} \\
-a_{12} & a_{22} & a_{23} & a_{24} \\
-a_{13} & a_{32} & a_{33} & a_{34} \\
-a_{14} & a_{42} & a_{43} & a_{44}
-\end{array}
-\right]
- \]
-
-}
-
-Then, it is clear that:
-\[
-{\bf A} \cdot {\bf x} = {\bf L}\cdot{\bf U}\cdot{\bf x} = {\bf b}
-\]
-So, we can solve for {\bf x} in two stages.  In the {\em forward substitution\/} stage,
-we find {\bf y} such that:
-\[
-{\bf L} \cdot {\bf y} = {\bf b}
-\]
-and then, in the {\em backward substitution\/} stage, we find {\bf x} such that:
-\[
-{\bf U} \cdot {\bf x} = {\bf y}
-\]
-
-Each of the last two equations involves triangular matrices, and so
-the solution is easy.
-For forward substitution:
-\[
-\begin{array}{llll}
-y_1 & = & \frac{b_1}{l_{11}} & \\
-y_i & = & \frac{1}{l_{ii}}\left[ b_i - \sum_{j=1}^{i-1}{l_{ij}y_j} \right] & \hspace*{1in} 2 \leq i \leq n
-\end{array}
-\]
-and, for backward substitution:
-\[
-\begin{array}{llll}
-x_n & = & \frac{y_n}{u_{nn}} & \\
-x_i & = & \frac{1}{u_{ii}}\left[ y_i - \sum_{j=i+1}^{n}{u_{ij}x_j} \right] & \hspace*{1in} 1 \leq i \leq (n-1)
-\end{array}
-\]
-
-Let us consider how to decompose {\bf A} into {\bf L} and {\bf U}.  It
-is clear from the equation ${\bf L}\cdot{\bf U} = {\bf A}$ that the
-$ij$'th element of {\bf A} is the inner-product of the $i$'th row of
-{\bf L} and the $j$'th column of {\bf U}, \ie\
-\[
-l_{i1}u_{1j} + l_{i2}u_{2j} + ... l_{in}u_{nj} = a_{ij}
-\]
-
-However, since $l_{ij}$ is zero whenever $i < j$ and $u_{ij}$ is zero
-whenever $i > j$, this equation can be separated into two cases (note
-the final term in each case):
-
-\[
-\begin{array}{llll}
-i \leq j: \hspace*{1cm} & l_{i1}u_{1j} + l_{i2}u_{2j} + ... l_{ii}u_{ij} & = & a_{ij} \\
-i   >  j:               & l_{i1}u_{1j} + l_{i2}u_{2j} + ... l_{ij}u_{jj} & = & a_{ij}
-\end{array}
-\]
-
-Further, it is always possible to choose the diagonal elements of {\bf
-L} (\ie\ $l_{ii}$) to be $1$.  The last two equations can then be
-rearranged as:
-
-\[
-\begin{array}{lllll}
-u_{ij} &
-= &
-&
-a_{ij} - \sum_{k=1}^{i-1}{l_{ik}u_{kj}} \hspace*{2cm} &
-1 \leq j \leq n, 1 \leq i \leq j \\
-% ----------------
-\vspace*{1ex} \\
-% ----------------
-l_{ij} &
-= &
-\frac{1}{u_{jj}} &
-\left(a_{ij} - \sum_{k=1}^{j-1}{l_{ik}u_{kj}} \right) &
-1 \leq j \leq n, j+1 \leq i \leq n
-\end{array}
-\]
-
-Since {\bf L}'s diagonal elements ($l_{ii}$) are assumed to be one, we
-do not compute them, and we do not store them.  When this diagonal of
-{\bf L} is omitted, the remaining {\bf L} and {\bf U} elements have
-disjoint indices.  Therefore, they can be stored in a single $n \times
-n$ matrix called {\bf LU}.  This structure, along with the computation
-of the {\bf L} and {\bf U} elements, is depicted in Figure
-\ref{skyline-1}.
-
- %
- \begin{figure}[htbp]
- \fbox{%
-   \parbox%
-     {\illuswidth}
-     {\illustration{skyline-1}{1.85 true in}
-      \caption{%
-         \label{skyline-1}
-         Computation of {\bf LU} from {\bf A}.
-              }
-     }}
- \end{figure}
- %
-
-The forward and backward substitution computations are depicted in
-Figures \ref{skyline-2} and \ref{skyline-3}, respectively.
-
- %
- \begin{figure}[htbp]
- \fbox{%
-   \parbox%
-     {\illuswidth}
-     {\illustration{skyline-2}{1.5 true in}
-      \caption{%
-         \label{skyline-2}
-         Solving ${\bf L}\cdot{y} = {\bf b}$ (forward substitution)
-              }
-     }}
- \end{figure}
- %
-
- %
- \begin{figure}[htbp]
- \fbox{%
-   \parbox%
-     {\illuswidth}
-     {\illustration{skyline-3}{1.5 true in}
-      \caption{%
-         \label{skyline-3}
-         Solving ${\bf U}\cdot{x} = {\bf y}$ (backward substitution)
-              }
-     }}
- \end{figure}
- %
-
-% ----------------------------------------------------------------
-
-\subsection{LU decomposition of dense matrices}
-
-The Id code for LU decomposition of a dense matrix follows the
-equations given above exactly (Figure \ref{skyline-1}):
-
-\begin{minipage}{\textwidth}
- \begin{idenv}
-def LUDCMP\_dense A =
-  \{ (\_,\_),(\_,n) = matrix\_bounds A ;
-\null
-    LU = \{matrix (1,n),(1,n)
-          | [i,j] = ufn i j || j <- 1 to n & i <- 1 to j         % upper
-          | [i,j] = lfn i j || j <- 1 to n & i <- (j+1) to n \} ; % lower
-\null
-    def ufn i j = sum\_down 1 (i-1) A[i,j] (term i j) ;           % upper
-\null
-    def lfn i j = (1/LU[j,j]) * (sum\_down 1 (j-1) A[i,j] (term i j)) ; % lower
-\null
-    def term i j k = LU[i,k]*LU[k,j] ;
-   In
-     LU \} ;
- \end{idenv}
-\end{minipage}
-
-In the first line in the block, we find $n$, the dimension of the
-problem. The primitive function {\cf matrix\_bounds} returns the index
-bounds of {\bf A}, represented as a pair of pairs. The pattern on the
-left-side of the binding shows this pair-of-pairs structure, and
-ignores three of the components (using ``{\cf \_}'' for a
-``dont-care'' pattern) and binds {\cf n} to the fourth.  Here, we are
-assuming that {\cf A} has bounds (1,n),(1,n)--- it would be quite easy
-to bind all four components and verify that this is indeed so.
-
-The second binding defines the actual {\bf LU} matrix, using Id's
-array comprehension notation.  It specifies the contents of the
-2-dimensional array in two regions corresponding to {\bf U} and {\bf
-L}, respectively, using the functions {\cf ufn} and {\cf lfn}.  Each
-expression of the form \mbox{\cf (sum\_down $k_1$ $k_2$ $a$ $f$)}
-computes
-\[
-a - \sum_{k=k_1}^{k_2}{f(k)}
-\]
-the Id code for which is:
-
-\begin{minipage}{\textwidth}
- \begin{idenv}
-def sum\_down k1 k2 a f = \{for k <- k1 to k2 do
-                            next a = a - (f k)
-                          finally a \} ;
- \end{idenv}
-\end{minipage}
-
-Here is the code for the forward and backward substitutions.  Again,
-the code is self-evident, corresponding exactly to the equations and
-Figures \ref{skyline-2} and \ref{skyline-3}.
-
-\begin{minipage}{\textwidth}
- \begin{idenv}
-def LUBKSB\_dense LU B =
-  \{ (\_,n) = bounds B ;
-\null
-    Y = \{vector (1,n)
-         | [1] = B[1]
-         | [i] = sum\_down 1 (i-1) B[i] (yfn i) || i <- 2 to n\} ;
-\null
-    def yfn i j = LU[i,j] * Y[j] ;
-\null
-    X = \{vector (1,n)
-         | [n] = Y[n] / LU[n,n]
-         | [i] = (1/LU[i,i])*
-                 (sum\_down (i+1) n Y[i] (xfn i)) || i <- (n-1) downto 1 \} ;
-\null
-    def xfn i j = LU[i,j] * X[j] ;
-   In
-     X \} ;
- \end{idenv}
-\end{minipage}
-
-% ----------------------------------------------------------------
-
-\subsection{LU decomposition of skyline matrices}
-
-In Figure \ref{skyline-1}, in each inner-product, note that the low
-index of each component vector is always 1.  In a skyline matrix, on
-the other hand, the low index of the horizontal vector will be some
-$i1 \geq 1$ and the low index of the vertical vector will be some $j1
-\geq 1$.  Thus, the inner product can be ``clipped'' to begin at $max(i1,j1)$.
-
-A second important observation is that it is clear from the equations
-that the {\bf LU} matrix will always have exactly the same skyline
-shape as the original {\bf A} matrix, so that the data structure for
-{\bf LU} can be identical to the data structure for {\bf A}.
-
-The data structures that we choose for {\bf A} (and {\bf LU}) is shown in Figure
-\ref{skyline-4}. The sub-diagonal elements of {\bf A} are held in {\bf AL}, which is an
-$n$-vector of vectors.  The $i$'th row is represented by a vector with
-dimensions $(j1,i-1)$, where $1 \leq j1 \leq i$ is the minimum index.
-When $j1 = i$, the lower index is greater than the lower index,
-representing an {\em empty\/} row vector.  These are depicted by
-little circles ``$\circ$'' in the figure.  The diagonal and
-super-diagonal elements of {\bf A} are held in {\bf AU}, which is also
-an $n$-vector of vectors.  The $j$'th row is represented by a vector
-with dimensions $(j1,j)$, where $1 \leq j1 \leq j$ is the minimum
-index.  Note that none of the column vectors can be empty.
-
- %
-\begin{figure}[htbp]
- \fbox{%
-   \parbox%
-    {\illuswidth}
-    {\illustration{skyline-4}{1.35 true in} 
-     \caption{%
-        \label{skyline-4}
-        Data structure for {\bf A} ({\bf LU} is similar).
-            } 
-    }} 
-\end{figure}
- %
-
-The code for the decomposition function is shown in Figure
-\ref{ludcmp-sky-program}.  In the definition of {\cf U}, the $j$'th
-column vector is specified as a vector with the same bounds as the
-$j$'th column vector in {\cf AU} (from {\cf i1} to {\cf j}).  In
-calling {\cf ufn}, we supply it {\cf i1} and {\cf j1}, the lowest
-indices of the column vector and row vector of the inner-product.  In
-{\cf ufn}, we clip the iteration to begin at {\cf $max({\tt i1},{\tt j1})$}.
-A similar strategy is used in the specification of {\cf L}.
-
-\begin{figure}[htbp]
- \hdivider
-\begin{idenv}
-def LUDCMP\_sky (AL, AU) =
-    \{ (\_,n) = bounds AU ;
-\null
-      U = \{vector (1,n)
-           | [j] = \{ (i1,\_) = bounds  AU[j]
-                    In
-                      \{vector (i1,j)
-                       | [i] = \{ (j1,\_) = bounds  AL[i]
-                                In
-                                  ufn i1 j1 i j\}       || i <- i1 to j\}\}
-                                                          || j <- 1 to n\} ;
-\null
-      L = \{vector (2,n)
-           | [i] = \{ (j1,\_) = bounds  AL[i]
-                    In
-                      \{vector (j1,i-1)
-                       | [j] = \{ (i1,\_) = bounds  AU[j]
-                                In
-                                  lfn i1 j1 i j\}       || j <- j1 to (i-1)\}\}
-                                                          || i <- 2 to n\} ;
-\null
-      def ufn i1 j1 i j = sum\_down  (max i1 j1)  (i-1)  AU[j][i]  (term i j) ;
-\null
-      def lfn i1 j1 i j = (1/U[j][j]) *
-                          (sum\_down  (max i1 j1)  (j-1)  AL[i][j]  (term i j)) ;
-\null
-      def term i j k = L[i][k] * U[j][k] ;
-    In
-      L,U \} ;
-\end{idenv}
- \caption{%
-    \label{ludcmp-sky-program}
-    LU decomposition for skyline matrices.
-         }
- \hdivider
-\end{figure}
-
-The code for forward and backward substitution is shown in Figure
-\ref{lubksb-sky-program}. Recall that in the dense version, {\cf yfn} was defined thus:
-
-\beginid
-    def yfn i j = LU[i,j] * Y[j] ;
-\endid
-
-Now, however, the term {\cf LU[i,j]} must be replaced by {\cf
-L[i][j]}.  However, {\cf L[i]} is fixed for each {\cf sum\_down}
-traversal, and so we optimize it by passing the entire row vector {\cf
-L[i]} to {\cf yfn}, which then just indexes it with {\cf j}.
-
-\begin{figure}[htbp]
- \hdivider
-\begin{idenv}
-def LUBKSB\_sky (L,U) B =
-  \{ (\_,n) = bounds B ;
-\null
-    Y = \{vector (1,n)
-         | [1] = B[1]
-         | [i] = \{ (j1,\_) = bounds  L[i]
-                  In
-                    sum\_down j1 (i-1) B[i] (yfn L[i] i)\} || i <- 2 to n\} ;
-\null
-    def yfn Li i j = Li[j] * Y[j] ;
-\null
-    X = \{vector (1,n)
-         | [n] = Y[n]  / U[n][n]
-         | [i] = (1/U[i][i])*
-                 (sum\_down (i+1) n Y[i] (xfn i)) || i <- (n-1) downto 1 \} ;
-\null
-    def xfn i j = \{ uj = U[j] ;
-                    (i1,\_) = bounds uj ;
-                   In
-                     if (i < i1) then
-                       0.0
-                     else
-                       Uj[i] * X[j] \} ;
-   In
-     X \} ;
-\end{idenv}
- \caption{%
-    \label{lubksb-sky-program}
-    Forward and backward substitution for skyline matrices.
-         }
- \hdivider
-\end{figure}
-
-In {\cf xfn}, we run across the following problem: the inner-product
-traverses a {\em row\/} of {\cf U}.  However, because of our
-representation of the skyline {\cf U}, not all elements in a
-particular row may be present.  So, our code first extracts the $j$'th
-column vector, and then extracts the index bounds of that vector.  If
-$i$ is outside the bounds, the term is 0; otherwise, we extract the
-normal $LU[i,j]$ (\ie\ $U[j][i]$, which is {\cf Uj[i]}).
-
-Of course, this conditional is executed $O(n^2)$ times (once for every
-position in the upper triangle).  We could trade time for space by
-first reformatting {\cf U} into a full upper triangular matrix (filling
-in all the zeroes) and then indexing it as usual.  We do not pursue
-this possibility here.
-
-Finally, the top-level function to solve a given set of equations is
-shown in Figure \ref{solve-sky-program}, where we assume that {\cf A}
-is a pair of skylines {\cf (AL,AU)}.
-
-\begin{figure}[htbp]
- \hdivider
-\begin{idenv}
-def solve\_sky (A,B) = LUBKSB\_sky (LUDCMP\_sky A) B ;
-\end{idenv}
- \caption{%
-    \label{solve-sky-program}
-    Top-level skyline matrix solver.
-         }
- \hdivider
-\end{figure}
-
-\subsection{Test runs}
-
-We generated a random $50 \times 50$ {\cf A} matrix (\ie\ picked a
-random envelope and filled with random numbers) containing 1210
-elements, \ie\ a density of about 50\%.  We also generated a
-randomly-filled {\cf B} vector of size 50.  Figure
-\ref{skyline-solve_sky_50} shows the parallelism profile generated by GITA
-when {\cf solve\_sky} is run on these inputs.
-Figures \ref{skyline-ludcmp_sky_50} and \ref{skyline-lubksb_sky_50}
-show the individual contributions of {\cf ludcmp\_sky} and {\cf
-lubksb\_sky}, respectively, to the composite parallelism profile.
-
-% Elapsed times: 429 secs and 341 secs and 45.5 secs
-
- \begin{figure}[htbp]
- \fbox{%
-   \parbox%
-     {\illuswidth}
-     {\illustration{skyline-solve_sky_50}{1.87 true in}
-      \caption{%
-         \label{skyline-solve_sky_50}
-         Parallelism profile for {\tt solve\_sky} ($50 \times 50$ example)
-              }
-     }}
- \end{figure}
-
- \begin{figure}[htbp]
- \fbox{%
-   \parbox%
-     {\illuswidth}
-     {\illustration{skyline-ludcmp_sky_50}{1.87 true in}
-      \caption{%
-         \label{skyline-ludcmp_sky_50}
-         Parallelism profile for {\tt ludcmp\_sky} ($50 \times 50$ example)
-              }
-     }}
- \end{figure}
-
- \begin{figure}[htbp]
- \fbox{%
-   \parbox%
-     {\illuswidth}
-     {\illustration{skyline-lubksb_sky_50}{1.87 true in}
-      \caption{%
-         \label{skyline-lubksb_sky_50}
-         Parallelism profile for {\tt lubksb\_sky} ($50 \times 50$ example)
-              }
-     }}
- \end{figure}
-
-It is clear that almost all the parallelism in the skyline matrix
-solver is in the LU decomposition stage.  This is actually quite
-obvious if we analyze Crout's algorithm, which exhibits ``wavefront''
-parallelism.  Each element in the LU matrix depends only on those
-above it and to the left, so that a frontier that is perpendicular to
-the diagonal can be computed in parallel.  This frontier sweeps across
-the matrix like a wave from the top left to the bottom right.
-
-In the forward and backward substitution stages, since the {\cf y} and
-{\cf x} matrices are filled using linear recurrences, there is hardly
-any parallelism at all.
-
-In languages with explicit parallelism, the wavefront parallelism of
-LU decomposition could be expressed with a little effort for dense
-matrices. We could have a sequential loop that iterates down the
-diagonal, and a nested, parallel loop that computes all the
-cross-diagonal elements in parallel.  Unfortunately, it does not
-appear so easy to extend such a solution to skyline matrices, because
-of the irregular shape of the cross-diagonals.  In Id, on the other
-hand, implicit parallelism gives us automatic producer-consumer
-synchronization, allowing it to adapt dynamically to such irregular
-parallel structures.
-----------------------------------------------------------------
-
-@article{
-    Arvind84,
-    key = "Arvind",
-    author = "Arvind and Brock, J. Dean",
-    title = "{Resource Managers in Functional Programming}",
-    journal = "Journal of Parallel and Distributed Computing",
-    volume = 1,
-    number = 1,
-    year = 1984,
-    month = "June",
-    annote = "non-determinism,  Id, Dataflow, parallelism, functional languages"
-}
-
-@inBook{
-    Arvind88b,
-    key = "Arvind",
-    author = "Arvind and Heller, S.K. and Nikhil, R.S.",
-    title = "{Programming Generality and Parallel Computers}",
-    booktitle = "Biological and Artificial Intelligence Systems,
-                 E. Clementi and S. Chin (eds)",
-    note = "Proceedings of the Fourth International Symposium on Biological and
-            Artificial Intelligence Systems, Trento, Italy",
-    publisher = "ESCOM Science Publishers, P.O.Box 214, 2300 AE Leiden, The Netherlands",
-    year = 1988,
-    month = "September",
-    pages = "255-286",
-    annote = "Id, functional languages, paraffins"
-}
-
-@article{
-    Hoare74,
-    key = "Hoare,C.A.R.",
-    author = "Hoare,C.A.R.",
-    title = "Monitors: an Operating System Structuring Concept",
-    journal = "Communications of the ACM",
-    volume = 17,
-    number = 10,
-    year = 1974,
-    month = "October",
-    pages = "549-557"
-}
-
-@book{
-    Knuth73,
-    key = "Knuth, D.E.",
-    author = "Knuth, D.E.",
-    title = "The Art of Computer Programming, Volume 1: Fundamental Algorithms",
-    publisher = "Addison Wesley",
-    address = "Reading, Massachusetts",
-    year = "1973"
-}
-
-@book{
-    Knuth73b,
-    key = "Knuth, D.E.",
-    author = "Knuth, D.E.",
-    title = "The Art of Computer Programming, Volume 2: Semi-Numerical Algorithms",
-    publisher = "Addison Wesley",
-    address = "Reading, Massachusetts",
-    year = "1973"
-}
-
-@techReport{
-    Nikhil88c,
-    key = "Nikhil, R.S.",
-    author = "Nikhil, R.S.",
-    title = "{Id (Version 88.1) Reference Manual}",
-    institution = "MIT Laboratory for Computer Science",
-    address = "545 Technology Square, Cambridge, MA 02139",
-    number = "CSG Memo 284",
-    year = 1988,
-    month = "August"
-}
-
-@book{
-    Nikhil90a,
-    key = "Nikhil, R.S.",
-    author = "Nikhil, R.S. and Arvind",
-    title = "{Programming in {\it Id\/}: a parallel programming language}",
-    year = 1990,
-    note = "(book, in preparation)"
-}
-
-@book{
-    Press86,
-    key = "Press, W.H.",
-    author = "Press, W.H. and Flannery, B.P. and Teukolsky, S.A. and Vettering, W.T.",
-    title = "{Numerical Recipes: The Art of Scientific Computing}",
-    publisher = "Cambridge University Press",
-    year = "1986",
-    pages = "31-35"
-}
-
-@inProceedings{
-    Turner81,
-    key = "Turner, D.A.",
-    author = "Turner, D.A.",
-    title = "The Semantic Elegance of Applicative Languages",
-    booktitle = "Proc. ACM Conference on Functional Programming Languages
-                 and Computer Architecture, Portsmouth, New Hampshire",
-    year = 1981,
-    month = "October",
-    pages = "85-92"
-}
-----------------------------------------------------------------
-
-%!postscript
-%%Creator: Illustrate Version 13.3
-%%CreationDate: 1/22/90 18:52:09
-%%Pages: 1
-%%BoundingBox: 79.568504 37.587402 485.65985 162.39685
-%%EndComments
-1 setlinecap 1 setlinejoin
-72 2540 div dup scale
-2807 1326 translate
-
-
-%% PostScript Illustrate Graphics Support
-
-/linewidth1 26 def
-
-/fill-box
-  { /cy exch def /cx exch def
-    /halfwidth width 2 div def
-    /halfheight height 2 div def
-    newpath
-     cx halfwidth sub cy halfheight sub moveto
-     0 height rlineto
-     width 0 rlineto
-     0 height neg rlineto
-     closepath
-     fill } def
-
-/point
-  { brushtype circlebrush eq
-     { halfthickness newpath 0 360 arc fill }
-     { brushtype squarebrush eq
-        { /height brushthickness def
-         /width brushthickness def
-         fill-box }
-        { brushtype verticalbrush eq
-           { /height brushthickness def
-            /width linewidth1 def
-            fill-box }
-           { /height linewidth1 def
-            /width brushthickness def
-            fill-box }
-          ifelse }
-        ifelse }
-     ifelse } def
-
-/circlebrush     1 def
-/squarebrush     2 def
-/verticalbrush   3 def
-/horizontalbrush 4 def
-
-/setbrushtype { /brushtype exch def } def
-
-/setbrushthickness
-  { dup /brushthickness exch def
-    dup 2 div /halfthickness exch def
-    setlinewidth } def
-
-/setbrush { setbrushthickness setbrushtype } def
-
-/simpleline { newpath moveto lineto stroke } def
-
-/complexline
-  { /y2 exch def /x2 exch def
-    /y1 exch def /x1 exch def
-    /halfwidth width 2 div def
-    /halfheight height 2 div def
-
-    % Make line go left to right.
-    x1 x2 gt { /x2 x1 /x1 x2 def def /y2 y1 /y1 y2 def def } if
-
-    y1 y2 gt
-     { % Line does down.
-       newpath
-        x1 halfwidth add y1 halfheight add moveto
-       x2 halfwidth add y2 halfheight add lineto
-       0 height neg rlineto
-        width neg 0 rlineto
-        x1 halfwidth sub y1 halfheight sub lineto
-        0 height rlineto
-        closepath
-       fill }
-     { % Line goes up.
-       newpath
-        x1 halfwidth sub y1 halfheight add moveto
-       x2 halfwidth sub y2 halfheight add lineto
-       width 0 rlineto
-       0 height neg rlineto
-       x1 halfwidth add y1 halfheight sub lineto
-       width neg 0 rlineto
-       closepath
-       fill }
-     ifelse } def
-
-/drawline
-  { brushthickness linewidth1 eq
-    % For thin lines ignore brushtype.
-    { simpleline }
-    { brushtype circlebrush eq
-       { % Draw a line in the circular brush.
-         simpleline }
-       { brushtype squarebrush eq
-          { % Draw a line in the square brush.
-            /width brushthickness def
-           /height brushthickness def
-           complexline }
-          { brushtype verticalbrush eq
-             { % Draw a line in the vertical brush.
-              /width linewidth1 def
-              /height brushthickness def
-              complexline }
-             { % Draw a line in the horizontal brush.
-              /width brushthickness def
-              /height linewidth1 def
-              complexline }
-             ifelse }
-          ifelse }
-       ifelse }
-    ifelse } def
-
-/to
- { /save-y exch def
-   /save-x exch def
-   save-x save-y drawline
-   save-x save-y } def
-
-/triangle
- { newpath moveto lineto lineto closepath fill } def
-
-circlebrush 26 setbrush
-1003 986 1014 936 to 1026 936 to 1037 1190 to 1049 1494 to 1060 1698 to 1072 1698 to 1083 1850 to 1094 1850 to 1106 1545 to 1117 1901 to 1129 1494 to 1140 2206 to 1152 2053 to 1163 2256 to 1174 2663 to 1186 2155 to 1197 2866 to 1209 2510 to 1220 3120 to 1232 3171 to 1243 3018 to 1254 3730 to 1266 2460 to 1277 3730 to 1289 3222 to 1300 3730 to 1312 3730 to 1323 2612 to 1334 3577 to 1346 2612 to 1357 3476 to 1369 3171 to 1380 3120 to 1392 3882 to 1403 2968 to 1414 3780 to 1426 3018 to 1437 3730 to 1449 3171 to 1460 2612 to 1472 3730 to 1483 2764 to 1494 3780 to 1506 3374 to 1517 3425 to 1529 3526 to 1540 2714 to 1552 3577 to 1563 2663 to 1574 3526 to 1586 3171 to 1597 2968 to 1609 3679 to 1620 2917 to 1632 3730 to 1643 2815 to 1655 3526 to 1666 2968 to 1677 2714 to 1689 3222 to 1700 2612 to 1712 3272 to 1723 2866 to 1735 2917 to 1746 3272 to 1757 2714 to 1769 3069 to 1780 2968 to 1792 3222 to 1803 3018 to 1815 2663 to 1826 3069 to 1837 2409 to 1849 3120 to 1860 2714 to 1872 32!
-72 to 1883 2968 to 1895 2612 to 19
-06 3222 to 1917 2612 to 1929 3171 to 1940 2764 to 1952 2764 to 1963 3069 to 1975 2612 to 1986 2968 to 1997 2663 to 2009 3069 to 2020 2815 to 2032 2663 to 2043 2968 to 2055 2663 to 2066 2866 to 2077 2510 to 2089 2561 to 2100 2663 to 2112 2460 to 2123 2663 to 2135 2409 to 2146 2714 to 2157 2612 to 2169 2714 to 2180 2764 to 2192 2358 to 2203 2815 to 2215 2460 to 2226 2764 to 2237 2612 to 2249 2307 to 2260 2968 to 2272 2460 to 2283 2968 to 2295 2612 to 2306 2561 to 2317 2612 to 2329 2561 to 2340 2764 to 2352 2307 to 2363 2663 to 2375 2764 to 2386 2409 to 2397 2714 to 2409 2460 to 2420 2663 to 2432 2307 to 2443 2561 to 2455 2358 to 2466 2510 to 2477 2612 to 2489 2256 to 2500 2714 to 2512 2510 to 2523 2561 to 2535 2460 to 2546 2307 to 2557 2510 to 2569 2002 to 2580 2510 to 2592 2256 to 2603 2460 to 2615 2612 to 2626 2155 to 2637 2612 to 2649 1901 to 2660 2409 to 2672 2155 to 2683 2002 to 2695 2307 to 2706 1799 to 2718 2104 to 2729 1901 to 2740 1952 to 2752 1748 to 2763 1850 to 277!
-5 1698 to 2786 1748 to 2798 1799 t
-o 2809 1799 to 2820 1748 to 2832 1901 to 2843 1799 to 2855 1799 to 2866 1799 to 2878 1799 to 2889 1799 to 2900 1647 to 2912 1748 to 2923 1952 to 2935 1748 to 2946 1952 to 2958 1748 to 2969 1901 to 2980 1596 to 2992 1901 to 3003 1698 to 3015 1748 to 3026 1748 to 3038 1647 to 3049 1799 to 3060 1748 to 3072 1748 to 3083 1901 to 3095 1748 to 3106 1901 to 3118 1748 to 3129 1952 to 3140 1748 to 3152 1901 to 3163 1748 to 3175 1901 to 3186 2104 to 3198 1698
- to 3209 1799 to 3220 2053 to 3232 1748 to 3243 2002 to 3255 1698 to 3266 1952 to 3278 1799 to 3289 1850 to 3300 1799 to 3312 1799 to 3323 1850 to 3335 1748 to 3346 1647 to 3358 1748 to 3369 1850 to 3380 1748 to 3392 1850 to 3403 1850 to 3415 1748 to 3426 1799 to 3438 1748 to 3449 1799 to 3460 1748 to 3472 1901 to 3483 1799 to 3495 1901 to 3506 1748 to 3518 1901 to 3529 1799 to 3540 1901 to 3552 1850 to 3563 1850 to 3575 1901 to 3586 1850 to 3598 2053 to 3609 1799 to 3620 1901 to 3632 1799 to 3643 1799 to 3655 1799 to 3666 1698 to 3678 1901 to 3689 1952 to 3700 1901 to 3712 1901 to 3723 1799 to 3735 1901 to 3746 1698 to 3758 1698 to 3769 1748 to 3780 1698 to 3792 1748 to 3803 1698 to 3815 1799 to 3826 1647 to 3838 1698 to 3849 1748 to 3860 1698 to 3872 1799 to 3883 1596 to 3895 1647 to 3906 1494 to 3918 1647 to 3929 1444 to 3941 1596 to 3952 1545 to 3963 1596 to 3975 1647 to 3986 1545 to 3998 1647 to 4009 1545 to 4021 1647 to 4032 1647 to 4043 1596 to 4055 1647 to 4066 1698 !
-to 4078 1596 to 4089 1545 to 4101 
-1698 to 4112 1545 to 4123 1545 to 4135 1647 to 4146 1545 to 4158 1647 to 4169 1444 to 4181 1596 to 4192 1596 to 4203 1748 to 4215 1799 to 4226 1545 to 4238 1698 to 4249 1494 to 4261 1698 to 4272 1647 to 4283 1748 to 4295 1748 to 4306 1393 to 4318 1799 to 4329 1647 to 4341 1748 to 4352 1748 to 4363 1748 to 4375 1698 to 4386 1494 to 4398 1799 to 4409 1545 to 4421 1545 to 4432 1799 to 4443 1698 to 4455 1647 to 4466 1393 to 4478 1698 to 4489 1494 to 4501 1748 to 4512 1698 to 4523 1342 to 4535 1748 to 4546 1444 to 4558 1596 to 4569 1748 to 4581 1444 to 4592 1748 to 4603 1444 to 4615 1748 to 4626 1393 to 4638 1748 to 4649 1596 to 4661 1494 to 4672 1647 to 4683 1494 to 4695 1647 to 4706 1596 to 4718 1799 to 4729 1698 to 4741 1647 to 4752 1850 to 4763 1494 to 4775 1850 to 4786 1799 to 4798 1545 to 4809 1698 to 4821 1545 to 4832 1748 to 4843 1494 to 4855 1698 to 4866 1494 to 4878 1799 to 4889 1545 to 4901 1545 to 4912 1596 to 4923 1545 to 4935 1647 to 4946 1647 to 4958 1494 to 4969 1!
-799 to 4981 1596 to 4992 1647 to 5
-004 1596 to 5015 1799 to 5026 1850 to 5038 1545 to 5049 1748 to 5061 1596 to 5072 1799 to 5084 1596 to 5095 1647 to 5106 1799 to 5118 1494 to 5129 1698 to 5141 1748 to 5152 1647 to 5164 1748 to 5175 1647 to 5186 1748 to 5198 1647 to 5209 1647 to 5221 1748 to 5232 1545 to 5244 1494 to 5255 1494 to 5266 1647 to 5278 1494 to 5289 1444 to 5301 1393 to 5312 1545 to 5324 1393 to 5335 1494 to 5346 1494 to 5358 1494 to 5369 1444 to 5381 1393 to 5392 1494 to
- 5404 1494 to 5415 1494 to 5426 1494 to 5438 1291 to 5449 1393 to 5461 1494 to 5472 1342 to 5484 1494 to 5495 1342 to 5506 1342 to 5518 1494 to 5529 1342 to 5541 1494 to 5552 1342 to 5564 1494 to 5575 1494 to 5586 1393 to 5598 1494 to 5609 1342 to 5621 1494 to 5632 1342 to 5644 1494 to 5655 1393 to 5666 1494 to 5678 1291 to 5689 1444 to 5701 1342 to 5712 1342 to 5724 1342 to 5735 1342 to 5746 1393 to 5758 1342 to 5769 1393 to 5781 1342 to 5792 1342 to 5804 1393 to 5815 1342 to 5826 1444 to 5838 1494 to 5849 1291 to 5861 1494 to 5872 1342 to 5884 1342 to 5895 1494 to 5906 1393 to 5918 1494 to 5929 1190 to 5941 1545 to 5952 1291 to 5964 1545 to 5975 1494 to 5986 1393 to 5998 1393 to 6009 1291 to 6021 1545 to 6032 1190 to 6044 1545 to 6055 1494 to 6066 1291 to 6078 1545 to 6089 1190 to 6101 1494 to 6112 1342 to 6124 1393 to 6135 1545 to 6146 1240 to 6158 1494 to 6169 1291 to 6181 1393 to 6192 1494 to 6204 1393 to 6215 1494 to 6227 1240 to 6238 1494 to 6249 1291 to 6261 1393 to !
-6272 1494 to 6284 1393 to 6295 149
-4 to 6307 1342 to 6318 1444 to 6329 1494 to 6341 1393 to 6352 1494 to 6364 1393 to 6375 1494 to 6387 1291 to 6398 1393 to 6409 1291 to 6421 1393 to 6432 1393 to 6444 1240 to 6455 1393 to 6467 1240 to 6478 1393 to 6489 1393 to 6501 1393 to 6512 1393 to 6524 1240 to 6535 1494 to 6547 1240 to 6558 1393 to 6569 1393 to 6581 1545 to 6592 1444 to 6604 1240 to 6615 1545 to 6627 1240 to 6638 1393 to 6649 1393 to 6661 1291 to 6672 1342 to 6684 1190 to 6695 1190 to 6707 1037 to 6718 1190 to 6729 1190 to 6741 1190 to 6752 1190 to 6764 1190 to 6775 1190 to 6787 1190 to 6798 1291 to 6809 1190 to 6821 1190 to 6832 1190 to 6844 1037 to 6855 1291 to 6867 1190 to 6878 1291 to 6889 1190 to 6901 1088 to 6912 1291 to 6924 1088 to 6935 1240 to 6947 1139 to 6958 1291 to 6969 1190 to 6981 1088 to 6992 1291 to 7004 1088 to 7015 1291 to 7027 1190 to 7038 1139 to 7049 1240 to 7061 1139 to 7072 1240 to 7084 1139 to 7095 1291 to 7107 1139 to 7118 1088 to 7129 1291 to 7141 1037 to 7152 1291 to 7164 1190!
- to 7175 1240 to 7187 1139 to 7198
- 1139 to 7209 1240 to 7221 1139 to 7232 1240 to 7244 1139 to 7255 1139 to 7267 1291 to 7278 1088 to 7290 1291 to 7301 1190 to 7312 1240 to 7324 1139 to 7335 1139 to 7347 1240 to 7358 1088 to 7370 1291 to 7381 1139 to 7392 1240 to 7404 1139 to 7415 1291 to 7427 1190 to 7438 1088 to 7450 1291 to 7461 1088 to 7472 1291 to 7484 1190 to 7495 1139 to 7507 1291 to 7518 1139 to 7530 1240 to 7541 1139 to 7552 1291 to 7564 1190 to 7575 1139 to 7587 1291 to 75
-98 1139 to 7610 1240 to 7621 1139 to 7632 1240 to 7644 1139 to 7655 1139 to 7667 1240 to 7678 1139 to 7690 1291 to 7701 1139 to 7712 1240 to 7724 1139 to 7735 1139 to 7747 1240 to 7758 1139 to 7770 1291 to 7781 1190 to 7792 1240 to 7804 1139 to 7815 1139 to 7827 1240 to 7838 1139 to 7850 1291 to 7861 1139 to 7872 1139 to 7884 1291 to 7895 1139 to 7907 1240 to 7918 1139 to 7930 1240 to 7941 1139 to 7952 1139 to 7964 1240 to 7975 1190 to 7987 1240 to 7998 1190 to 8010 1088 to 8021 1240 to 8032 1139 to 8044 1240 to 8055 1088 to 8067 1240 to 8078 1139 to 8090 1240 to 8101 1139 to 8112 1139 to 8124 1240 to 8135 1139 to 8147 1088 to 8158 1088 to 8170 986 to 8181 1037 to 8192 936 to 8204 1037 to 8215 834 to 8227 1037 to 8238 1037 to 8250 986 to 8261 1037 to 8272 936 to 8284 1037 to 8295 1037 to 8307 1037 to 8318 1037 to 8330 936 to 8341 1037 to 8352 885 to 8364 1037 to 8375 1037 to 8387 1037 to 8398 1037 to 8410 936 to 8421 1037 to 8433 885 to 8444 1037 to 8455 1037 to 8467 986 to !
-8478 1037 to 8490 936 to 8501 1037
- to 8513 834 to 8524 1037 to 8535 1037 to 8547 986 to 8558 1037 to 8570 936 to 8581 1037 to 8593 834 to 8604 1037 to 8615 1037 to 8627 1037 to 8638 1037 to 8650 936 to 8661 1037 to 8673 885 to 8684 1037 to 8695 1037 to 8707 986 to 8718 1037 to 8730 936 to 8741 1037 to 8753 834 to 8764 1037 to 8775 1037 to 8787 986 to 8798 1037 to 8810 936 to 8821 1037 to 8833 1037 to 8844 1037 to 8855 1037 to 8867 936 to 8878 1037 to 8890 885 to 8901 1037 to 8913 1037 to 8924 986 to 8935 1037 to 8947 936 to 8958 1037 to 8970 1037 to 8981 1037 to 8993 1037 to 9004 986 to 9015 1037 to 9027 936 to 9038 1037 to 9050 834 to 9061 1037 to 9073 1037 to 9084 986 to 9095 1037 to 9107 936 to 9118 1037 to 9130 1037 to 9141 1037 to 9153 1037 to 9164 986 to 9175 1037 to 9187 936 to 9198 1037 to 9210 1037 to 9221 1037 to 9233 1037 to 9244 936 to 9255 1037 to 9267 885 to 9278 1037 to 9290 1037 to 9301 986 to 9313 1037 to 9324 936 to 9335 1037 to 9347 1037 to 9358 1037 to 9370 1037 to 9381 936 to 9393 1037 t!
-o 9404 936 to 9415 1037 to 9427 10
-37 to 9438 1037 to 9450 1037 to 9461 986 to 9473 1037 to 9484 936 to 9495 1037 to 9507 1037 to 9518 1037 to 9530 1037 to 9541 936 to 9553 1037 to 9564 885 to 9576 1037 to 9587 885 to 9598 936 to 9610 682 to 9621 631 to 9633 631 to 9644 631 to 9656 631 to 9667 631 to 9678 631 to 9690 631 to 9701 631 to 9713 631 to 9724 631 to 9736 631 to 9747 631 to 9758 631 to 9770 631 to 9781 631 to 9793 631 to 9804 631 to 9816 631 to 9827 631 to 9838 631 to 9850 6
-31 to 9861 631 to 9873 631 to 9884 631 to 9896 631 to 9907 631 to 9918 631 to 9930 631 to 9941 631 to 9953 631 to 9964 631 to 9976 631 to 9987 631 to 9998 631 to 10010 631 to 10021 631 to 10033 631 to 10044 631 to 10056 631 to 10067 631 to 10078 631 to 10090 631 to 10101 631 to 10113 631 to 10124 631 to 10136 631 to 10147 631 to 10158 631 to 10170 631 to 10181 631 to 10193 631 to 10204 631 to 10216 631 to 10227 631 to 10238 631 to 10250 631 to 10261 631 to 10273 631 to 10284 631 to 10296 631 to 10307 631 to 10318 631 to 10330 631 to 10341 631 to 10353 631 to 10364 631 to 10376 631 to 10387 631 to 10398 631 to 10410 631 to 10421 631 to 10433 631 to 10444 631 to 10456 631 to 10467 631 to 10478 631 to 10490 631 to 10501 631 to 10513 631 to 10524 631 to 10536 631 to 10547 631 to 10558 631 to 10570 631 to 10581 631 to 10593 631 to 10604 631 to 10616 631 to 10627 631 to 10638 631 to 10650 631 to 10661 631 to 10673 631 to 10684 631 to 10696 631 to 10707 631 to 10718 631 to 10730 63!
-1 to 10741 631 to 10753 631 to 107
-64 631 to 10776 631 to 10787 631 to 10799 631 to 10810 631 to 10821 631 to 10833 631 to 10844 631 to 10856 631 to 10867 631 to 10879 631 to 10890 631 to 10901 631 to 10913 631 to 10924 631 to 10936 631 to 10947 631 to 10959 631 to 10970 631 to 10981 631 to 10993 631 to 11004 631 to 11016 631 to 11027 631 to 11039 631 to 11050 631 to 11061 631 to 11073 631 to 11084 631 to 11096 631 to 11107 631 to 11119 631 to 11130 631 to 11141 631 to 11153 631 to 11164 631 to 11176 631 to 11187 631 to 11199 631 to 11210 631 to 11221 631 to 11233 631 to 11244 631 to 11256 631 to 11267 631 to 11279 631 to 11290 631 to 11301 631 to 11313 631 to 11324 631 to 11336 631 to 11347 631 to 11359 631 to 11370 631 to 11381 631 to 11393 631 to 11404 631 to 11416 631 to 11427 631 to 11439 631 to 11450 631 to 11461 631 to 11473 631 to 11484 631 to 11496 631 to 11507 631 to 11519 631 to 11530 631 to 11541 631 to 11553 631 to 11564 631 to 11576 631 to 11587 631 to 11599 631 to 11610 631 to 11621 631 to 1163!
-3 631 to 11644 631 to 11656 631 to
- 11667 631 to 11679 631 to 11690 631 to 11701 631 to 11713 631 to 11724 631 drawline
-
-
-%% PostScript TeXFont Support for Illustrate
-
-/texfonts 128 array def
-/currenttexfont 0 def
-/currentfontdpi 0 def
-/currentrotation 0 def
-/currentbx 0 def
-/currentby 0 def
-
-/deftexfont
- { /newfont 129 array def
-   newfont exch 128 exch put
-   texfonts exch newfont put } def
-
-/settexrotation
- { /currentrotation exch def } def
-
-/settexfont
- { texfonts exch get dup /currenttexfont exch def
-   128 get /currentfontdpi exch def } def
-
-/deftexchar
- { /chardata exch def
-   /y-offset exch def
-   /x-offset exch def
-   true
-   1 0 0 1 x-offset y-offset 6 array astore
-   chardata
-   6 array astore /char exch def
-   texfonts exch get exch char put } def
-
-/texshow
- { /currentby exch def
-   /currentbx exch def
-   texshowinternal } def
-
-/texshowx
- { /currentbx exch def
-   texshowinternal } def
-
-/texshowy
- { /currentby exch def
-   texshowinternal } def
-
-/texshowinternal
- { gsave
-   currentbx currentby translate
-   2540 currentfontdpi div dup scale
-   currentrotation rotate
-   {texshowchar} forall
-   grestore } def
-
-/texshowchar
-   { currenttexfont exch get aload pop imagemask 0 translate } def
-
-/texrule
- { gsave
-   translate
-   currentrotation rotate
-   /height exch def
-   /width exch def
-   newpath
-    0 0 moveto
-    width 0 rlineto
-    0 height rlineto
-    width neg 0 rlineto
-    closepath
-    fill
-   grestore } def
-
-0 300 deftexfont
-55 0 21 17 28 -2 1 {{<03000007800007800007800007800007800003800003800003800003C00001C00001C00001C00000E00000E000006000007000003000003800C01800C01C00C00C00E00E00FFFE007FFF007FFF807FFF80600000>}} deftexchar
-48 0 21 18 27 -1 1 {{<03F0000FFC001E1E00380700380700780780700380700380F003C0F003C0F003C0F003C0F003C0F003C0F003C0F003C0F003C0F003C0F003C07003807003807807803807003C0F001E1E000FFC0003F000>}} deftexchar
-0 settexfont
-(70) 437.0 4136.0 texshow
-851 4136 1003 4136 drawline
-54 0 21 18 27 -1 1 {{<01F00007FC000E0E001C07003C07803803807803C07803C07803C0F803C0F803C0F803C0FC0380F40780F60700F30E00F1FC00F0F8007800007800003806003C0F001C0F000E070007860003FC0000F800>}} deftexchar
-(60) 427.0 3628.0 texshow
-1003 580 1003 4390 drawline
-67 0 30 25 29 -2 1 {{<003F800000FFF00003F0380007C00C000F0006001E0003003E0003003C0001807C0001807C00018078000180F8000000F8000000F8000000F8000000F8000000F8000000F8000180780001807C0001807C0003803C0003803E0007801E0007800F000F8007C01F8003F0798000FFE180003F8080>}} deftexchar
-114 0 16 15 18 0 1 {{<FFC0FFC01E001E001E001E001E001E001E001E001E001E001E001F0C1F1E1F9EFEFEFE7C>}} deftexchar
-105 0 12 10 29 -1 1 {{<FFC0FFC01E001E001E001E001E001E001E001E001E001E001E001E001E001E00FE00FE000000000000000000000000001C003E003E003E001C00>}} deftexchar
-116 0 16 12 25 -1 1 {{<07800FE01E603C303C303C303C303C303C303C003C003C003C003C003C003C00FFE0FFE03C001C001C000C000C000C000C00>}} deftexchar
-46 0 12 5 5 -3 1 {{<70F8F8F870>}} deftexchar
-112 0 23 20 26 -1 9 {{<FFC000FFC0001E00001E00001E00001E00001E00001E00001E7C001FFF001F87801E03C01E01E01E01E01E00F01E00F01E00F01E00F01E00F01E00F01E01E01E01E01E03C01F8780FFFF00FE7E00>}} deftexchar
-97 0 21 18 18 -2 1 {{<1F1F003FBF8078FCC0F07CC0F03CC0F03CC0703C00783C003C3C000F3C0001FC00003C00003C00303C00783C007878003FF0001FC000>}} deftexchar
-104 0 23 20 29 -1 1 {{<FF9FF0FF9FF01E07801E07801E07801E07801E07801E07801E07801E07801E07801E07801E07801E07801F07801F87001EFF001E3C001E00001E00001E00001E00001E00001E00001E00001E00001E0000FE0000FE0000>}} deftexchar
-108 0 12 10 29 -1 1 {{<FFC0FFC01E001E001E001E001E001E001E001E001E001E001E001E001E001E001E001E001E001E001E001E001E001E001E001E001E00FE00FE00>}} deftexchar
-101 0 18 15 18 -1 1 {{<07F00FF81E1C3C0E78067800F000F000F000FFFEFFFEF01E781E781C383C1C380FF003E0>}} deftexchar
-110 0 23 20 18 -1 1 {{<FF9FF0FF9FF01E07801E07801E07801E07801E07801E07801E07801E07801E07801E07801E07801E07801F07801F8700FEFF00FE3C00>}} deftexchar
-103 0 21 17 26 -2 9 {{<07E0001FF800781E00700E00E00700E00700E00700700F003FFE003FFC007FF0007000006000006FC0003FE000387000703800F03C00F03C00F03C00F03C00F03C00703800387B801FFF800FCF80>}} deftexchar
-58 0 12 5 18 -3 1 {{<70F8F8F870000000000000000070F8F8F870>}} deftexchar
-57 0 21 18 27 -1 1 {{<07E0001FF000383C003C1E003C0E00180F0000078000078000078007C3C00FF3C01C1BC0380BC07807C07007C0F003C0F003C0F003C0F00380F00780F00780700700780F00380E001C3C000FF80003E000>}} deftexchar
-44 0 12 5 13 -3 9 {{<C0E070303818181878F8F8F870>}} deftexchar
-51 0 21 16 27 -2 1 {{<07C01FF03878603CE01EE01FF01FF01F601F001F001E001E003C00780FC00FE000F00038003C301E781E781E701E701C383C1FF007C0>}} deftexchar
-56 0 21 16 27 -2 1 {{<0FE01FF87C1C780EF007E007E007E007E007E00FF01F787E3CFE1FFC0FF00FF01FF83F3C7E1C781E700E700E700E301E1C7C0FF807E0>}} deftexchar
-52 0 21 18 27 -1 1 {{<03FFC003FFC0003C00003C00003C00003C00003C00FFFFC0FFFFC0E03C00703C00303C00383C001C3C000C3C000E3C00073C0003BC0001BC0001FC0000FC00007C00007C00003C00001C00001C00000C00>}} deftexchar
-84 0 30 26 29 -2 1 {{<07FFF80007FFF800001E0000001E0000001E0000001E0000001E0000001E0000001E0000001E0000001E0000001E0000001E0000001E0000001E0000001E0000001E0000001E0000001E0000C01E00C0C01E00C0E01E01C0E01E01C0E01E01C0F01E03C0781E07807E1E1F807FFFFF807FFFFF80>}} deftexchar
-111 0 21 18 18 -1 1 {{<03F0000FFC001E1E00380700780780700380F003C0F003C0F003C0F003C0F003C0F003C07003807807803807001E1E000FFC0003F000>}} deftexchar
-115 0 16 13 18 -1 1 {{<CFC0FFE0F830E018E018C018C03801F81FF03FE07FC0FE00E030C030C07060F03FF01FB0>}} deftexchar
-49 0 21 14 27 -4 1 {{<FFFCFFFC07800780078007800780078007800780078007800780078007800780078007800780078007800780FF80FF800F8003800180>}} deftexchar
-(Crit.) 10083.0 3882.0 texshow
-(path) 10925.0 texshowx
-(length:) 11745.0 texshowx
-(9,384) 12916.0 texshowx
-(T) 10083.0 3546.0 texshow
-(otal) 10308.0 texshowx
-(op) 11010.0 texshowx
-(erations) 11391.0 texshowx
-(:) 12723.0 texshowx
-(116,739) 12938.0 texshowx
-90 settexrotation
-(ops) 146.0 2245.0 texshow
-851 3628 1003 3628 drawline
-53 0 21 16 27 -2 1 {{<0FC01FF03878603CE01EE01EF01FF01F601F001F001F001E301E383C3C383FF037E0300030003000300030003FE03FF83FFC3FFE3806>}} deftexchar
-0 settexrotation
-(50) 432.0 3120.0 texshow
-851 3120 1003 3120 drawline
-(40) 427.0 2612.0 texshow
-851 2612 1003 2612 drawline
-(30) 432.0 2104.0 texshow
-851 2104 1003 2104 drawline
-50 0 21 16 27 -2 1 {{<FFFEFFFE7FFE3FFF38071C030E0306030700038001C000E000F00078003C003E003E601FF01FF01FE01FC01F603E603E387C1FF807E0>}} deftexchar
-(20) 1596.0 texshowy
-851 1596 1003 1596 drawline
-(10) 441.0 1088.0 texshow
-1003 580 12433 580 drawline
-851 1088 1003 1088 drawline
-(0) 603.0 580.0 texshow
-851 580 1003 580 drawline
-(1,000) 1768.0 72.0 texshow
-2146 580 2146 428 drawline
-(2,000) 2906.0 texshowx
-3289 580 3289 428 drawline
-(3,000) 4049.0 texshowx
-4432 580 4432 428 drawline
-(4,000) 5189.0 texshowx
-5575 580 5575 428 drawline
-(5,000) 6335.0 texshowx
-6718 580 6718 428 drawline
-(6,000) 7475.0 texshowx
-7861 580 7861 428 drawline
-(7,000) 8624.0 texshowx
-9004 580 9004 428 drawline
-(8,000) 9764.0 texshowx
-10147 580 10147 428 drawline
-(9,000) 10904.0 texshowx
-11290 580 112