Summary: This article is a sequel to an earlier paper, part of which described the basic facilities of the simplified programming system (Autocode) developed for the Ferranti Mercury Computer at Manchester University. The present article describes further facilities of the system and, together with the earlier description, amounts to a compact programming manual for the Manchester Mercury Computer.
In those arithmetical instructions involving a variable expression on the right-hand side, each sum, difference and product is formed to a maximum precision of 29 binary digits and then rounded off by making the last digit odd. If required, the rounding operation can be omitted by using the ≈ sign instead of =. In this case the result will normally be biased, but if the quantities involved can be expressed in at most 29 significant binary digits, then the ≈ sign provides a means of performing exact arithmetical operations on variables.
Rounding errors will be significant when using the int pt and fr pt instructions. Thus for example:
if x = 3 + 2-27, then int pt (x) gives 3 and fr pt (x) gives 2-27 if x = 3 - 2-27, then int pt (x) gives 2 and fr pt (x) gives 1-2-27 if x = 3 precisely, then int pt (x) gives 3 and fr pt (x) gives 0.2-256
However, precise whole numbers can only be obtained as a result of unrounded (≈) arithmetical operations (which include simple transfers, mod and int pt, but do not include division in any form) on numbers originally read in (see Note 4) as integers.
If the nearest integer to x is intended, it is sufficient to use (say)
y = int pt(x + 0-5)
unless x itself is half an odd integer, in which case the result will again depend critically on rounding errors.
The instructions
i = max (x0, n, m) i = min (x0, n, m)
may be used to determine the index of the maximum (or minimum) element in the range
xn, xn+1, ... , xm
Here i denotes any index, x0 any first member, and n, m are indices or whole numbers. If there is no unique maximum (or minimum) element, then the least index is taken.
Special facilities are provided for the integration of differential equations. The equations must be written in the form
fi = dyi/dx = fi(x,y1,y2,...yn) (i = 1,2,...n)
involving the special variable x, the main variables yi , fi and the index n. In addition the special variable h is used for the step length, and the main variables gi , hi , i=1,2,...n) are introduced for working space. The programmer must write a subsequence for calculating the fi in terms of x and the yi ; this must not alter yi , gi , gi , n, h or x. The entry should be labelled, and the sequence should terminate with the special instruction 592, 0.
Mercury programmers will recognise this as an ordinary machine instruction. Subject to certain restrictions it is possible to include such instructions in an Autocode program, but this is a topic beyond the scope of the present article since it involves a detailed knowledge of conventional Mercury programming. The interested reader may refer to the paper by Fotheringham and Roberts on p. 128.
With these arrangements the effect of the instruction
int step (m)
(where m is the entry to the subsequence) is to advance the integration by one step so that the initial and final values of the independent and dependent variables are respectively
x x + h yi(x) yi(x+h)
The method employed is that of Runge-Kutta, with a truncation error of 0(h5). However, the truncation error also depends on the higher derivatives of the function, and for this reason the step length may be adjusted between steps if desired. The time per step is (10n + 4T)msec, where T is the time (in msec) of the subsequence.
Integrate the two equations:
dy1/dx = y1 2 - 1.23y1 2 + 2.47y2 2 dy2/dx = 1.01y1 2 - 0.84y1 2 + 1.59y2 2
for x = 0(.02)1, with the initial conditions:
(a) x = 0; y1 = 0;y2 = 1 (b) x = 0; y1 = 1;y2 = 0
Program Notes chapter 1 | f→2 | g→2 | main directives h→2 | y→2 | 1) n=2 | sets the number of equations h=0.02 | the step length x=0 | and the first initial conditions y1=0 | y2=1> | 2) int step(3) | advances the step newline | print(x, 1, 2) | space | prints with layout print(y1, 2, 4) | print(y2, 2, 4) | jump 2, 0.99 > x | repeat until x = 1 restart | prepare to read the second set of initial conditions 3) f1=y1y1 - 1.23y1y2 + 2.47y2y2 | subsequence to calculate f1, f2 f2=1.01y1y1 - 0.84y1y2 + 1.59y2y2 | 592,0 close ........... across 1/1 | first chapter 0 starts the calculation .............. x=0 | second chapter 0 sets second initial conditions y1=1 y2=0 across 2/1 close ............. stop | third chapter 0 stops the machine close
This example introduces the instruction
restart
which is used to read in further instructions. These will usually be confined to chapter 0, as in this case, and used to re-enter an existing program. The restart instruction may also be used, however, to read in a fresh program.
The diagram shows the general layout of a program involving three chapters.
chapter 1 directives instructions close chapter 2 directives instructions close chapter 3 directives instructions close acrose ?/? close
Each chapter has its own labelling system, and to jump from one chapter to another an across instruction may be used: for example, one of the form
across 2/3
meaning jump to the instruction labelled 2 in chapter 3. Since this is a rather long instruction (100 msec) it is preferable not to include it within an inner loop and, as far as possible, partition into chapters should correspond to distinct parts of the calculation.
chapter 0 has two special features:
(1) It is entered automatically, at the first instruction, when the close directive is read.
(2) The directives used are those of the chapter last read, unless chapter 0 is actually headed chapter 0, in which case the directives must be formally set, either in the usual way or by means of the variables directive explained in the following section.
The main variables must be defined at the beginning of each chapter either explicitly or, if it is a case of repetition, by means of a directive of the form
variables 2
meaning use the directives set in chapter 2 - which of course may have been those used in chapter 1. It may be necessary to appreciate the significance of the variable directives. Thus
chapter 1 a → 99 allocates memory locations 0 - 99 to a0-a99 b → 99 allocates memory locations 100 - 199 to b0-b99 c → 99 allocates memory locations 200 - 299 to c0-c99 chapter 2 c → 99 allocates memory locations 0 - 99 to c0-c99 x → 49 allocates memory locations 100 - 149 to x0-x49 y → 49 allocates memory locations 150 - 199 to y0-y99
Thus the c's of chapter 2 are not those of chapter 1; if it is intended that they should be, then the latter directives might be recast as follows:
x → 49 y → 49 π → 99 (waste) c → 99
A further consequence of this scheme is that x50" is identical with y0, x51 with y1 and so on. Such overlapping references are sometimes useful.
To supplement the 495 working variables there are approximately 10,000 auxiliary variables to which indirect access is possible, the exact number depending on the requirements of the program. (The number of auxiliary variables is given by 10,751 - 512n, where n is the highest chapter number. Up to 3,072 further variables can be obtained subject to certain restrictions on the program. (Details available on request.)) Such access is a time-consuming operation, however, and should only be used when the working variables are insufficient for the problem in hand. In order to refer to these variables, fourteen new working variables
a' b' c' d' e' f' g' h' u v' w' x' y' z'
are introduced. These are essentially similar to the special variables a, b,...z and indeed may be used as such if desired. It is intended, however, that these variables will be used to designate groups of auxiliary variables. This is done by means of instructions in the program proper (unlike the main variables which are described by means of directives) which set these variables to give the address within the auxiliary stores (0, 1,... 10,751) of the first member of an auxiliary group.
Thus, for example, the instructions
a' ≈ 0 b' ≈ 100 x' ≈ 200 y' ≈ 1200 or alternatively a' ≈ 0 b' ≈ a' + 100 x' ≈ b' + 100 y' ≈ c' + 1000
designate two groups a', b' of 100 variables, a group x' of 1,000 variables, and a group y' of unlimited extent. In contrast to the main variable directives the quantity on the right-hand side is the starting-point and not the extent of the group, although in both cases the extent is irrelevant if overlapping is allowed. Note that the ≈ form of the arithmetical instructions has been employed since the quantities in question are whole numbers.
To specify a particular member of a group (say s') the notation
x'750 or x'u
is employed, where the suffix (in the one-dimensional form) is essentially a variable (an index cannot be used because there is no limit to the size of a group).
The instruction φ1(x'750, a1,10) is an example of an auxiliary transfer. It means transfer 10 consecutive variables from the auxiliary store to the working store, starting at x750 in the former, and at a1 in the latter. As a result a1, a2,...a10 are replaced by x750,x751,...x759. The instruction φ2(x'750,a1,10) corresponds to the reverse operation, namely a transfer from the working store to the auxiliary store. In these instructions x'750 may be replaced by any particular auxiliary variable, e-g- x'u, y'0, and a1 by any main variable, e.g. a0 or b(i-1). The third parameter 10 is essentially an index quantity and may be replaced by an index letter.
Examples of auxiliary transfers are
φ1(x'0,a0,400) φ2(x'g,bi,i) φ2(x'hi,c(r-1),t)
An exception to the rule that the second parameter must be a main variable is provided by the instruction
φ1(x'750,a,1)
which replaces the special variable a by x'750.
The execution time for a group transfer cannot be given very precisely but is less than
{l7[n/32] + 34 + 0.36n} msec
where [ ] denotes integral part of, and n is the number of variables transferred.
At any point within a chapter it is possible to call in a subchapter and subsequently to return to the original chapter at the instruction following the point of departure. This is done by means of a down instruction in the main chapter and an up instruction in the subchapter. For example
down 2/3
calls in chapter 3 as a subchapter and enters it at the instruction labelled 2. When the subchapter has completed its task the single word instruction
up
will return control to the main chapter at the instruction following the original down instruction. Alternatively the up instruction may be used in any chapter reached by means of across instructions from the original sub-chapter. A subchapter may have its own sub-subchapter but there the regression stops.
If necessary the working variables (i.e. main and special) can be preserved during the operation of the subchapter and subsequently restored on return to the main chapter. This can be done by means of the single-word instruction reset used before the down instruction; the variables are dumped on the magnetic drum and subsequently restored by the corresponding up instruction. As a consequence, any results calculated by the subchapter would have to be stored as auxiliary variables if they were to be preserved. However, if subchapters are designed to select from and return to the drum all relevant material, they provide a convenient means of arranging a calculation for possible future use as a subprogram. The subchapters can be written without defining the auxiliary variables. Instead the special variables a', b', c', etc., can be defined in terms of those used in the main chapter, by including appropriate instructions between the reset and down instructions. Since they follow the reset instruction the original values of a', b', c', etc., will be restored on returning to the main chapter. In this way each level of organisation may use its own frame of reference for the auxiliary variables. As an example suppose that both the main chapter and the subchapter employ three groups of auxiliary variables denoted in both cases by a', b', c', and starting relative to each other as follows:
a'(sub) == c'(main) b'(sub) = a'(main) c'(sub) - b'(main) + 50
These relations may be represented diagrammatically thus:
main chapter a'......................b'.......... .......c'.................. subchapter b'...................... ::::::::::c'.......a'.................. <- 50 ->
The instructions for calling in the subchapter and redefining the auxiliary variables are then as follows:
reset π≈a' a'≈c' c'≈b'+50 b'≈π down ?/?The special variable ≈ has been used as a shunting station since, in any case, it will be reset on entering the new chapter (≈ is automatically reset to 3.14159 ... as a result of the instructions across, down, up, and reset).
9. OPERATIONS WITH COMPLEX NUMBERS
Operations with complex numbers written as number pairs are provided by instructions of the form
(u, v) = (x, y) (u, v) = (x, y) _ (a, b) (u, v) = (x, y) - (a, b) (u, v) = (x, y) * (a, b) (u, v) = (x, y) / (a, b) (u, v) = sq rt (x, y) (v > 0) (u, v) = log (x, y) (π > v > -π) (u, v) = exp (x, y)
Further functions may be added. Here u, v; x, y, a, b denote any variables or (except in the case of u, v) signed constants.
Examples of instructions in this class are:
(fi,gi) = (f(i-1), g(i-1)) + (f(i+1), g(i+1)) (x, y) = sq rt(1, 1) (a, b) = log(-0.5, h)
Every time one of the functions
sq rt cos log tan radius sin exp arctan
is referred to, 17msec are spent in transferring the necessary set of instructions (subroutine) from the magnetic drum to the instruction store. Provided there is room, however, they can be included in the chapter itself, and in this case the average execution time is reduced from about 23 msec to 6 msec. Functions treated in this way are known as quickies. All that is necessary is to list them (each preceded by φ) in order of preference at the end of the chapter in question, immediately before the close directive (as shown below). Any functions for which there is not room will be treated in the usual way.
chapter 1 ............ ............ ............ φ exp φ sq rt φ sin close
As regards the complex functions, these involve the use of certain real functions, as follows:
complex sq rt involves sq rt complex exp involves exp, sin, cos complex log involves log, arctan.
Thus in order to treat the complex functions as quickies, it is sufficient to list the relevant real functions. Finally, it should be mentioned that sin and cos involve the same set of instructions, so that if either one is treated as a quicky the other will be also. The same applies to sq rt and radius.
1. Printing: all numerical values are rounded off by adding ½.10-m, m being the number of decimal places specified.
2. In the case of numbers ≥ 1016 an asterisk only is printed.
3. The ? print facility does not apply to the complex-number instructions.
4. Numbers may be read either directly, by means of a read instruction, or implicitly as constants on the right-hand side of an equation. In either case the number of digits after the decimal point is limited to 24 (no limit on integral part).
5. The description of the arctan function (given in the earlier article) is incomplete. The function calculates an angle in the range (-π, π), the quadrant being determined as if x,y were proportional to the cosine and sine of the angle respectively.
The author is indebted to Dr B Richards for advice and assistance at various stages of the work, and has also benefited from discussions with various friends and colleagues, in particular Dr J Howlett of AERE Harwell, and Dr GE Thomas of the Central Instrument Laboratory, ICI, Ltd.