The APL\360 Terminal System ABSTRACT:
This paper discusses the salient features of the system,
and its relation to mathematics,
primarily from the point of view
of a scientifically oriented user.
The cover is designed from an example of an interaction between computers and the physical and mathematical sciences. The design depicts ion trajectories in a type of mass spectrometer used for chemical analysis of residual gases in ultrahigh vacuum system. These ion trajectories represent solutions of Mathieu’s differential equation. They are generated by numerical integration of the equation using a high speed computer, and are plotted automatically from an output tape as part of the Research Center computing service. INTRODUCTION APL\360 is an experimental interactive system, programmed for IBM System/360 computers, which uses typewriter terminals connected to the central machine by telephone lines for both input and output. The basis of the system is APL [1, 2, 3, 4], a truly machinefree* programming language which leans heavily on mathematical notions, but does not slavishly follow classical mathematical notation. Correspondingly, the running system, which is completely interpretive, makes no significant concessions to implementation problems. This paper will discuss the salient features of the system, and its relation to mathematics, primarily from the point of view of a scientifically oriented user. The structure of the implementation is described in a companion paper. [5] * That is, the primitive operations in APL are defined without reference to the representation of the arguments. LANGUAGE CHARACTERISTICS The primitive objects of APL are symbols and (real) numbers, and functions defined on these domains. Functions are either monadic or dyadic, and in accordance with usual practice, the former have their single argument to the right, while the latter have an argument on each side. The syntactic limitation to a maximum of two arguments — which arises in an obvious way with a linear notation — is not a significant restriction, since any argument may, in fact, be an array. Complete definitions of primitive APL functions
are given in the APL\360 manual
[4].
However, Tables 1 and 2
(which lists the functions implemented
as of the date of this paper,
together with a descriptive phrase for each)
provide a basis for a number of observations
on the characteristics of the language.
Scalar Functions Most of the symbols do double duty, as both monadic and dyadic functions — a versatility usually found only in the minus sign. The rule for deciding the valence of a function symbol is simple: A function is dyadic if it is immediately preceded by a constant or a variable (or a parenthesized expression). Thus, there is no confusion between a+÷b and a÷b (assuming that a and b are variables); or between 7+4⌊3.14 and 7+⌊3.14 , which evaluate, respectively, to 10.14 and 10 . The last example raises a question regarding the sequence in which operations in a compound statement are to be executed, since 7+4⌊3.14 might have been evaluated (taking the sum first) as 3.14 . The rule here is again a simple one: There is no hierarchy among functions, and every function takes as its righthand argument the entire expression to its right. Parentheses are used to delimit expressions, and therefore indicate, in the usual way, departures from the order of execution otherwise determined by the structure of a compound statement. For a sequence of monadic functions such as h g f x , this rule gives the usual interpretation: f x is evaluated first, g takes that result as its argument and h operates on the result of g . That is, the execution sequence is from right to left although the expression is usually spoken from left to right. Thus, “the reciprocal of the absolute value of the floor of minus 3.14” is written as ÷⌊3.14 , and evaluates to 0.25 . The righttoleft order of execution
allows certain important functions involving
nonassociative operators to be written
more simply than other rules would allow.
For example, abcde is the alternating
sum (a+c+e less b+d),
and a÷b÷c÷d÷e is the alternating
product (a×c×e divided by b×d).
Also, the simple succession of exponentiations, a*b*c
means a raised to the b*c power.
(The other possibility, a*b raised
to the c power,
is equivalent to a raised
to the b×c power,
and may be written as a*b×c).
The factored form for a polynomial
in z ,
with coefficients a , b , c ,
and d ,
is written without parentheses,
as a+z×b+z×c+z×d ;
and a continued fraction can be written
on one line, also without parentheses,
as a+÷b+÷c+÷d .
Numbers and Arrays Numbers are written in decimal notation, with two further conventions. Constants involving a power of 10 can be written using the “e notation“, and a negative number is named by a high horizontal bar, as in ¯2 . Examples of both conventions are 3e5 , ¯2e3 , 5.72e¯4 , and ¯1.4e¯3 , which could also be written as 300000 , ¯2000 , 0.000572 , and ¯0.0014 . Numbers so represented are distinguished from expressions such as 3×10*5 , ¯2×10*3 , 5.72×10*¯4 , and ¯1.4×10*¯3 , which evaluate to the same results. The distinction between constants and expressions is carried over to arrays, and a constant vector is written as a sequence of numerical constants, with no punctuation other than spaces between them, as 3e5 ¯2 4.1 ¯1.4e¯3 . The same vector could be formed by the process of catenation, using the operator “,”, which would, in fact, be required if any element of the vector were itself not a constant. A vector has a “rank” of one, the term being used, as in tensor analysis, to mean the number of indices required to identify a single element in an array. Hence, a scalar has rank zero and a matrix has rank two. This is shown in Table 3, which illustrates the behavior of the dimension function ⍴ . As implied by this table, ⍴ operating on an array always in a vector. A second application of ⍴ then yields the rank of the original array. Vectors and other arrays in APL are neutral, and represent nothing more than an ordered collection of numbers and symbols, as the case may be. A vector comprised of ones and zeros, for example, is not itself a binary number, any more than a vector comprised of digits from 0 to 9 is a decimal number. A function of the vector must be invoked to find the number represented, if that is the intention. Similarly, the numbers themselves do not depend for their meaning on how they are derived. The relations, for example, map into 0 or 1, for false or true, and the results are treated simply as numbers. To maintain simplicity and generality,
no elision of operators
is permitted in APL statements.
At best, only one such elision could be tolerated,
and this would make the language undesirably
dependent upon its context.
The added convenience in one particular field
of application would be offset
by the relative inconvenience in others.
Functions Applied to Arrays Referring again to Table 1, it will be observed that the dyadic scalar primitives are extended to rectangular arrays in four ways. No special notational convention is required for the elementbyelement extension, so that in the expression a+b , for example, a and b may be any pair of matching arrays. If one argument is a scalar the other may be any array, and the operation is defined as if the scalar argument were a matching array comprised of identical elements. As a consequence of this, many expressions composed with only a scalar in mind are nonetheless valid for arrays of higher rank. For example, in the polynomial form given above (that is, a+z×b+z×c+z×d), z could well be a vector or matrix. In fact, any one of the coefficients could be a nonscalar array, provided that the other variables were scalars, or arrays of matching size. Similarly, the generic expression for a single term of a series is usually valid for any number of terms if the running variable is a vector. Thus, (x*n)÷!n is either the n^{th} term of the expansion of e^{x}, the entire series, or an arbitrary set of terms, depending upon whether n is a single integer, the sequence 1,2,3, ... , or some other set of integers. The extension of scalar dyadic primitives in “reduction” uses a composite symbol, comprising the operator symbol followed by a solidus, as in +/a . The meaning is derived formally by inserting the operator between the elements of the array; for example, +/3 7 9 2 is equivalent to 3 + 7 + 9 + 2 . The term “reduction” refers to the relative rank of the resulting array; if a is a vector, +/a yields a scalar, if a is a matrix +/[2]a yields a vector of rowsums and +/[1]a yields a vector of column sums, etc. If a is a scalar or a singleelement vector, reduction by any operator yields the scalar itself; if a is an empty vector, reduction yields the identity (if it exists) for the operator. These rules carry over to reduction the commutativity and associativity of scalar operators, and often allow special cases to be included in general expressions without special provision. For example, ×/⍳n is equal to factorial n for integer n≥0 . This is explicated as follows: ⍳n generates a vector of integers 1,2,...,n , and in general ⍴⍳n is exactly n . Hence, ⍳1 is the vector 1 and ×/⍳1 equals 1 . Since ⍳0 is an empty vector (⍴⍳0 equals 0), ×/⍳0 gives the identity for multiplication, which is also equal to 1 . Using reduction, an alternative expression for a polynomial with c as a vector of coefficients, and e the vector of exponents, is +/c×x*e . In the standard form for a polynomial of degree d , e is the vector of integers 0,1,...,d , which can be written as ¯1+⍳⍴c . The polynomial may therefore be written as +/c×x*¯1+⍳⍴c . It will be useful later on to take advantage of the fact that elementbyelement multiplication of vectors is commutative, and write this as +/(x*¯1+⍳⍴c)×c . Along the same lines,
the evaluation of the series for e^{x},
up to t terms, can be written
as +/(x*n1)×!n1 ,
where n has the value ⍳t .
The evaluation of e^{x} is just as simply written,
as /(x*n1)×!n1 ,
since the reduction by minus gives
the alternating sum.
The last expression could also be used
to evaluate t terms of the series
for sine or cosine by setting n
to 2×⍳t or ¯1+2×⍳t ,
respectively.
Inner and Outer Products The inner product is indicated in APL by the compound symbol comprised of two operators with a period between, as in a+.×b . This example is the ordinary scalar product if a and b are vectors, or the usual matrix product if the arguments are matrices. The notation reflects the fact that a matrix product is generated by an elementbyelement operation followed by a reduction. Virtually any pair of scalar dyadic operators has a meaningful interpretation as inner product in some context: p×.*e will generate a number from its prime factors p and their powers e ; a+.≥b will count the number of positions in which a dominates b ; the series for e^{x} can be written as (x*n1).÷!n1 ; etc. The result of an inner product is an array with rank two less than the sum of the argument ranks. The result of an outer product, on the other hand, is always an array of rank equal to the sum of the argument ranks. This follows from the fact that the reduction operation, which collapses two dimensions in an inner product, is not used in the outer product. The notation for outer product reflects this by canonically using a small circle as the first symbol. Thus, the ordinary outer product is written as a∘.×b . The outer product with operators other than × has great utility. For example, if n has the value ⍳t , then n∘.=n , n∘.<n , n∘.≥n , and ÷¯1+n∘.+n are respectively the identity matrix, a strict upper triangle matrix, a lower triangle matrix, and a Hilbert matrix, all of dimension t by t . The expression for a polynomial can be written
as an inner product: (x*¯1+⍳⍴c)+.×c .
In this form it can be used to evaluate a given polynomial
of arbitrary degree for a single value of x only;
to generalize it further — allowing x
to be an array of arbitrary rank and dimension —
it is merely necessary to use the outer product
thus: (x∘.*¯1+⍳⍴c)+.×c .
Other Array Operations Single elements or subarrays can be selected from arrays by naming their location (indexing), or by pointing to their locations in an array having a related structure (compression). Arrays as a whole may also be transposed (⍉), rotated (⌽), or completely restructured (dyadic ⍴). These operations are defined for arrays of any rank, although a practical upper limit for arrays in APL\360 is about 12. The notation for indexing employs square brackets, which follows the name of the array and enclose a number of expressions equal to the rank of the array. Expressions within the index may themselves evaluate to arrays, and in all cases the resultant array will have a dimension vector composed of the catenated dimension vectors of the indices. The absence of an expression where one might appear in an index means the selection of all components along the corresponding axis. Thus, columns or rows may be selected from matrices, lines or planes from threedimensional arrays, etc. A matrix may be partitioned into arbitrary submatrices by using appropriate partitions of its index sets. For example, if a and b are partitions of the row indices, and c and d are partitions of the column indices, then the four submatrices of a matrix q would be given by q[a;c] , q[a;d] , q[b;c] , and q[b;d] . If t is an n by n matrix representing the multiplication table for a semigroup whose elements are represented by ⍳n , then the test for associativity of the operation is given by ^/^/^/t[t;]=t[;t] . If u is a vector of distinct elements, and p is a predicate defined for the elements of u , then p u is a vector of the same dimension as u , but composed only of ones and zeros. The expression (p u)/u will select from u only those elements for which p is true. This is an example of compression, which is more generally defined for vectors and other arrays whose elements need not necessarily be distinct. Like reduction, compression is applied to matrices by columns or by rows, but compression always produces a subarray of the same rank as the original array. For example, if m is a matrix, (m[;1]=⌈/m[;1])/[1]m is the matrix comprising those (one or more) rows of m which contains as their first element the largest value found in the first column. If u is a set of numbers, and the predicate is the relation 0=4u , then (0=4u)/u is the set comprising elements of u which are exact multiples of four. There is a simple relationship between this form and ordinary set notation: {x:x∊u and 4x} . The major difference lies in the suppression in APL of the dummy variable x , and the requirement that the universe always be named explicitly. The transposition operator in APL illustrates one of the guiding principles in the design of the language: The ordinary use is obtained simply, but is a special case of a more general and powerful operation. Thus, used monadically on a matrix, ⍉m gives the ordinary transpose, which is also equivalent to the dyadic form, 2 1 ⍉m . For arrays of rank above 2 , this is generalized to an inversion of the last two coordinates; e.g., if a is a three dimensional array, ⍉a is equivalent to 1 3 2⍉a . The dyadic form is again generalized to permit repetitions in left arguments, as in 1 2 1 ⍉a . This produces a matrix whose second coordinate is the second coordinate of a , and whose first coordinate is taken along the diagonal where the first and third coordinates of a run together. That is, the result is a diagonal plane of a . For a matrix, 1 1 ⍉m is simply the main diagonal of m , and is a vector. If r is the resultant array and t⍉a is the operation, then for all cases the structure of r is given by the relatively simple formulation: (⍴r)[i] is equal to ⌊/(t=i)/⍴a , for all i in ⍳⍴r . Used monadically, the symbol ⌽ reverses the order of its argument. For instance, ⌽⍳3 is the sequence 3 2 1 . Used dyadically, the left argument causes an endaround shift to the left. Thus, 2⌽⍳5 is 3 4 5 1 2 and ¯2⌽⍳5 is 4 5 1 2 3 . In both cases, application to arrays of higher rank requires an index to choose the affected coordinates, as in reduction or compression. Thus, if m is a 5row matrix, (⍳5)⌽[2]m will rotate the first row by one, the second row by two, etc. The dyadic ⍴ obeys the relation that if r is the result of s⍴a , then ⍴r is equal to s . As many elements of a are used as are required to make up the full complement for r (equal to ×/s), and a is used repetitively if necessary. Thus, 3 3 ⍴ 1 0 0 0 will form the 3 by 3 unit matrix; and 1 ⍴ 4 5 6 will result in the vector 4 . Generally, n⍴m⌽v will select the m+1^{st} to m+n^{th} elements of v . If the right hand argument for ⍴
is an array of rank higher than one,
its elements are used in the sequence
of “row major order”.
This is also the order of elements
in the vector produced
by “ravelling” the array,
indicated by the use of the monadic comma.
Thus ,3 3 ⍴ 1 0 0 0
is the vector 1 0 0 0 1 0 0 0 1 .
Programming Primitives Everything discussed so far can be regarded as simply extensions and modifications to ordinary algebraic notation, and APL can be used similarly, for investigating the relationships among mathematical entities by formal manipulation. The additional primitive required for a programming language is the notion of specification, or replacement of one value by another. The symbol for this in APL is the leftpointing arrow, the equal sign being reserved for use only as one of the six relations. Because statements such as z←z+1 (read, z is “replaced by” or “specified by” z+1) are meaningful, specification carries with it the notion of sequence. A more explicitly sequential operator
is the branch,
designated by a rightpointing arrow,
which is used to indicate the sequence
to follow in executing a set of statements.
The normal sequence follows a succession
of statements written one below the other.
A branching statement alters the sequence
if the expression to the right
of the arrow evaluates to a number
other than that of the next succeeding statement.
If it evaluates to an empty vector
the normal sequence is unchanged.
Defined Functions New functions are defined in APL by programs, which may be regarded simply as formal statements of algorithms. In general, may different programs may define the same function, and any one of them is a particular representation of that function. Two examples of simple programs are show in Figure 1.^{*} One finds the n^{th} prime, the other computes and displays Pascal’s triangle up to the n^{th} power. * Note that, in general, entries from the keyboard are indented relative to machine output. The formal function definition facility provides for six syntactic forms, which fall into two classes, depending upon whether they have explicit resultants. The six possibilities are shown in Table 4, and the programs in Figure 1 illustrate the cases of monadic functions with and without explicit resultants. As shown in these examples, the syntax of the function is prescribed in the “header” of the function definition, the variables appearing in the header being regarded strictly as dummy variables. Identifiers set off by semicolons are “local” variables, which have no value outside of the function. Defined functions with explicit resultants are treated like their analogs among the primitive functions, and may be used freely in compound statements. The analog to a function so defined has the properties of one: it may enter into a computation as an argument to any other function, but because it is a function it cannot appear as the left argument to a specification. This is illustrated in Figure 2. Functions without explicit resultants find use for generating displays or for producing implicit results (“global” variables) to be used subsequently by functions having implicit arguments — a standard technique in ordinary programming practice. There is no necessary relationship between the syntax
of a defined function and the complexity
of the program necessary for defining it.
This makes it possible to tailor
a set of functions to a particular application,
such as conventional mathematical analysis,
and use them with the APL primitives always available.
A simple illustration of this is the set of
ten programs in Figure 3
which can be used for complex arithmetic
on arrays representing complex numbers.
Another illustration is Figure 4,
which is a program for matrix inversion,
based on GaussJordan elimination.
SYSTEM CHARACTERISTICS APL\360 is built around the idea of a workspace, analogous to a notebook, in which one keeps work in progress. The workspace holds both defined functions and variables (data), and it may be stored into and retrieved from a library holding many such workspaces. When retrieved from a library by an appropriate command from a terminal, a copy of the stored workspace becomes active at that terminal, and the functions defined in it, together with all the APL primitives, become available to the user. The three commands required for managing a library are “save”, “load”, and “drop”, which respectively store a copy of an active workspace into a library, make a copy of a stored workspace active, and destroys the library copy of a workspace. Each user of the system has a private library into which only he can store. However, he may load a workspace from any of a number of common libraries, or if he is privy to the necessary information, from another user’s private library. Functions or variables in different workspaces can be combined, either item by item or all at once, by a fourth command, called “copy”. By means of three cataloging commands, a user may get the names of workspaces in his own or a common library, or get a listing of functions or variables in his active workspace. A statement entered at a terminal
is executed immediately,
and if the result is not assigned to a variable,
it is printed out.
This deskcalculatorlike operation
makes the system very convenient
for casual use or experimental exploration.
Intermediate results may be retained
as named variables,
and used at any subsequent time.
Values must be assigned to variables
prior to their attempted use;
the value of a given variable may be respecified
at any time,
and it always retains
only the last value assigned.
Representation of Variables and Numbers There is no practical limitation to the length of names of variables, the only requirement being that they comprise only alphabetic or numeric characters, and start with an alphabetic. No special statement is required for establishing that a variable is to be an array, nor is there any fixed association between variable names and the kinds of values they represent. APL does not recognize any distinction
between “fixed point”
and “floating point” numbers,
this being primarily a matter of the representation
in a particular medium,
and the user of the terminal system
need have no concern with such questions
unless his work strains the capacity of the machine
with respect to either space or accuracy.
Although three different representations
for numbers are used internally,
transformations between them are carried out
automatically and the user can be completely
indifferent to the underlying machine
if 16 decimal digits are adequate for his work.
For operations such as floor and ceiling,
and in comparisons for equality,
a “fuzz” of about 10^{13}
is applied in order to avoid anomalous results
that might otherwise be engendered
by doing decimal arithmetic on a binary machine.
However, this factor can be controlled
within the system
(although not by a terminal command),
and a workspace with a fuzz of zero
is available for certain work
in numerical analysis.
Time and Space With regard to space, a workspace can hold about 250000 numbers derived from logical operations (0 or 1), about 8000 integers up to 2^{31} in value, about 4000 larger integers or fractional numbers, or about 32000 symbols. Since userdefined programs are retained substantially in their input form, they require relatively little storage, and the workspace size of 36000 System/360 bytes has proven to be adequate for very many problems. As a rough measure, it may be noted that real matrices as large as 35 by 35 can be multiplied and matrices 15 by 15 can be worked with comfortably. The system has a fast response to inputs
which require only minimal amounts of computation,
such as individual calculations with scalars,
or the steps in function definition.
Thus, there is no visible delay upon entering a line
in the course of defining a function,
since the terminal responds
with the next succeeding line number
in about the time it take for return
of the type carrier.
The response to longer calculations
is necessarily a function of the kind of work
that other users happen to be
doing at the moment.
Operational Features The system is completely interpretive; that is, there is translation to machine language only at the time of execution, each time a statement or defined function is executed. Because of the array operations in APL, however, the overhead associated with the translation is often very small relative to the amount of work being done. The multiplication of two 35 by 35 matrices, for example, requires the interpretation of only 5 symbols, and takes less than 16 seconds on a Model 50 machine on which the system is currently operating. The inversion of a 15 by 15 matrix by the defined function show in Figure 4 takes about 10 seconds of compute time. The generation and summation of 2000 integers (+/⍳2000) takes half a second. Statements entered into the system are not checked for validity until their execution is attempted, at which time the nature of the offense is printed, followed by a copy of the offending statement and a mark indicating where in the statement the difficulty was encountered. If the statement is part of a program, the name of the program and the line number are included in the display. Two features of the system make this kind of operation feasible: First, except for the initial specification of a function header, there is no procedural difference between the original definition of a function and later changes. Lines can be inserted and deleted simply, a single statement can be altered without affecting others, and single characters can be changed without the need for retyping an entire statement. It is possible to reopen a function definition, correct an error, and close the definition on a single line. Second, having completed the correction, it is possible to continue the execution of a function by entering a command to branch to the line number at which it stopped. Thus, work up to that point is not necessarily wasted. This ability to continue execution from where it has stopped has more general application. It is possible to plan a stop in a long or complex computation for the purpose of examining intermediate results, or merely to put off completion to another time. In the second case the workspace is stored in a library with the program in its suspended state, and upon subsequent retrieval of the workspace, it can be restarted. Planned stops are accomplished by means of a family of distinguished variables whose values are the line numbers at which stops are desired. It is also possible to stop a calculation by an interrupt from the keyboard at any arbitrary time. In either case, the number of the next line to be executed is automatically provided and execution may be resumed as above. Other means of interacting with a program during execution are provided by the trace and the quad. The trace uses a family of distinguished variables, like the stop, to signify the statements whose results are to be printed during execution. The quad (⎕) is used for indicating input or output. A quad to the left of a specification arrow calls for display of the assigned value, and it may even be used thus within compound statements to print the intermediate results developed during their execution. Without the specification arrow, a quad is a request for input, and execution is halted pending an entry from the keyboard. Examples of these uses are shown in Figure 5. Erasures are accomplished by backspace and line feed;
anything to the right of a line feed during
statement entry is considered to be erased.
Backspaces, therefore, have the same character
as forward spaces,
serving only to position the typing head.
This has two benefits:
it permits the use of overstruck symbols,
such as ⍉ and ! ,
and it avoids the ambiguity that obtains
when overstriking is used for corrections.
In general, the system has “visual fidelity”
— as long as platen and type carrier
are not moved manually,
the system sees exactly when appears
on the hard copy,
regardless of the order of entry.
SUMMARY The system has been designed to minimize the distraction of a user from his problem, while not disguising the fact that he is working with a machine. The advantages that accrue from the discipline imposed by a machine are not diluted by the imposition of tasks which are essentially only clerical. Thus, on the one hand, the burden has been placed on the machine wherever sufficient information is available in the normal course of events, as in the automatic handling of number representations and arrays, and in the production of output at the terminal when no other destination is specified. On the other hand, necessary messages to the user are as brief and impersonal as possible, and any attempt at guessing what was “really meant” in the case of obvious error is strictly avoided. In the first ten months of its existence,
the APL\360 terminal system has attracted
more than 200 users
within the IBM Research establishment.
Mathematical applications
include work in statistical mechanics,
design of ultrareliable computer systems,
experimental teaching of secondary school mathematics,
and the algebraic manipulation of polynomials.
It has proven attractive to many scientists
and engineers who heretofore have resisted
direct association with computers or programming.
ACKNOWLEDGMENT The authors wish to acknowledge
the direct contributions of L.M. Breed,
R.H. Lathwell, R.D. Moore, and L. Woodrum,
all of whom worked on the implementation.
Breed, in particular, has contributed substantially
to many of the aspects of the system
described in this paper,
as well as having led the implementation effort.
We are indebted, also, to many other
of our colleagues at IBM
for discussions arising
from their use of the system.
REFERENCES
TABLES Table 1. Scalar Primitive Operations Operations Defined on Scalar Arguments, Yielding a Scalar as Result
Table 2. Mixed Primitive Operations Operations involving arrays of diverse rank
Table 3. Dimensions of Vectors and Ranks of Arrays
Table 4. Header Forms in Function Definition
FIGURES Figure 1. Examples of Monadic Defined Functions
Figure 2. Example of Defined Function Without Arguments ∇ z←pi [1] z←3.141592653589793 ∇ a←2×pi a 6.283185307 pi÷6 0.5235987756 pi←22÷7 SYNTAX ERROR pi←22÷7 ∧ Figure 3. Set of Functions for Complex Arithmetic on Arrays ∇ z←a cadd b [1] z←a+b ∇ ∇ z←a csub b [1] z←ab ∇ ∇ z←a cmpy b [1] z←(⍴a)⍴(,/[1]a×b),,+/[1]a×⌽[1]b ∇ ∇ z←a cdiv b [1] z←(a cmpy conj b)÷(⍴a)⍴+/[1]b*2 ∇ ∇ z←conj b;t [1] t←0.5××/⍴b [2] z←b×(⍴b)⍴(t⍴1),t⍴¯1 ∇ ∇ z←comp a [1] z←⍉((0.5×⍴a),2)⍴a ∇ ∇ z←d rho x;a [1] a←0.5××/⍴x [2] z←(2,d)⍴((×/d)⍴(a⍴x)),(×/d)⍴⌽a⍴⌽,x ∇ ∇ z←real a [1] z←((~(⍴⍴a)⍺1)⍴a)/⍴a ∇ ∇ z←imag a [1] z←((~(⍴⍴a)⍺1)/⍴a)⍴⌽[1]a ∇ ∇ z←mod a [1] z←(+/[1]a×a)*0.5 ∇ Figure 4. Matrix Inversion by GaussJordan Elimination With Pivoting ∇ b←rec a;p;k;i;j;s [1] →3×⍳(2=⍴⍴a)∧=/⍴a [2] →0=⍴⎕←'no inverse found' [3] p←⍳k←s←1⍴⍴a [4] a←((s⍴1),0)\a [5] a[;s+1]←s⍺1 [6] i←j⍳⌈/j←a[⍳k;1] [7] p[1,i]←p[i,1] [8] a[1,i;⍳s]←a[i,1;⍳s] [9] →2×⍳1E¯30>a[1;1]÷⌈/,a [10] a[1;]←a[1;]÷a[1;1] [11] a←a((~s ⍺ 1)×a[;1])∘.×a[1;] [12] a←1⌽[1]1⌽a [13] p←1⌽p [14] →5×⍳0<k←k1 [15] b←a[;p⍳⍳s] ∇ Figure 5. Use of Quad and Quoted Quad for Output and Input ⎕←5×4×3×2×1 120 5×4×3×2×1 120 5×⎕←4×⎕←3×⎕←2×⎕←1 1 2 6 24 120 5×⎕×3×⎕×1 ⎕: 2 ⎕: 4 120 s←'example of ',⍞,' input using composite ',⍞ symbol. literal ⍴s 48 s example of literal input using composite symbol. Originally appeared as Research Report RC1922, 19671016.
