SATN-45
Language Extensions of May 1983
 

A number of language extensions are available in the May 1983 release of SHARP APL:

  Extension of the operatorto allow specification of the ranks of the cells to which a function applies (in the form f⍤(m,l,r) ).
  Extension of the right domains of the compositions f⍤g and f⍥g ) and dual f¨g ).
  New functions: Lev (), Dex (), and Link ().
  Extensions of matrix inverse and division () to arrays of rank greater than 2.

The Rank Operator

Definition

The operator On () previously only applied to two functions to provide Composition. It now accepts an integer right argument (as in ,⍤2 ) to specify the rank, or ranks, of the subarrays to which the function applies. For example:

      a←2 3 4⍴⍳24
   
      ,⍤2 a
 0  1  2  3  4  5  6  7  8  9 10 11
12 13 14 15 16 17 18 19 20 21 22 23
   
      ,⍤¯1 a
 0  1  2  3  4  5  6  7  8  9 10 11
12 13 14 15 16 17 18 19 20 21 22 23

As illustrated above, a non-negative argument specifies the number of final axes to which the function applies. A negative argument specifies the complementary rank, i.e., the number of leading axes to be excluded. The magnitude of the argument serves only to limit the number of axes; for the a given above, f⍤4 a ←→ f⍤3 a , and f⍤¯4 a ←→ f⍤¯3 a .

In the dyadic case two ranks (or complementary ranks) are specified. For example:

      e←2 2⍴'abcd' 
      f←2 2⍴'1234'

      e,⍤1 2 f
ab
12
34

cd
12
34

      e,⍤0 0 f
a1
b2

c3
d4

The most general right argument of is a three-element vector whose successive elements specify the monadic, left, and right ranks. A shorter argument r is extended so that f⍤r ←→ f⍤(⌽3⍴⌽r) . If the right argument of On is a scalar, and the resulting derived function is used dyadically, that number will specify the rank of both arguments.

An expression such as f⍤r a introduces the possibility of juxtaposing constants (r and a). If r is a constant, and if the expression defining a begins with a constant, then the division between the two constants must be made clear to prevent them from being treated as a single vector. For example, the sequence

      a←2 3 4⍴⍳24
      r←2
      ,⍤r a

cannot be written in a single line as

      ,⍤2 2 3 4⍴⍳24

but must be written in a form which separates the vector constants. For example:

      ,⍤(2) 2 3 4⍴⍳24

      ,⍤2 (2 3 4)⍴⍳24

      ,⍤2 a←2 3 4⍴⍳24

      ,⍤2⊢ 2 3 4⍴⍳24

If a function has rank r , then the subarrays along the last r axes of its arguments are the cells of the array. The remaining axes are the frame of the array. Consider the expression ⌹a , where a has the shape 8 7 6 5 4 .

     has argument rank 2
 The cells are arrays of shape 5 4.
 The frame has shape 8 7 6.

In contrast, consider the expression ⌊a , using the same array a .

     has argument rank 0.
 The cells are scalars, that is, arrays of shape ⍳0 .
 The frame has shape 8 7 6 5 4.

A function applies independently to each cell (or pair of cells, if dyadic) to produce result cells, which must be of common shape. The result is formed by assembling the frame of result cells into an array.

If a function f has rank r , then the result of f ⍵ is determined by:

1)  applying f to each of the cells of shape (-r)↑⍴⍵ ,
2)  producing results with a common shape sir for each,
3)  assembling the whole into a result of shape ((-r)↓⍴⍵),sir .

The frames of the arguments of a dyadic function must match in shape, or one of them must be a scalar. If the frame is a scalar, it is extended by reshaping it to match the shape of the other frame. This is a generalization of scalar extension.

By convention, if the frame is empty (i.e. 0∊(-r)↓⍴⍵ ), then the empty vector is used as the result cell shape.
 

Examples

Common uses for the Rank operator include:

1)  Applying functions of infinite rank (such as Enclose and Ravel) to sub-arrays, within multi-dimensional arrays, and
2)  Applying scalar functions (such as Addition) in ways that would not otherwise be possible under the rules of ordinary scalar extension.

The following examples illustrate uses of the Rank operator.

   v←⍳5 ⋄ x←10×⍳4 ⋄ y←100×⍳3 ⋄ w←v ⋄ m←3 4⍴⍳12 ⋄ n←?m ⋄ b←3 4 
5⍴⍳60
   q←2 5⍴'abcdeedbca' ⋄ ⎕ps←-1 1 3 3

Examples with Enclose

      m
1  2  3  4
5  6  7  8
9 10 11 12

      <⍤0 m                  Enclose each (scalar) element
|¯| |¯|  |¯|  |¯|
|1| |2|  |3|  |4|
|_| |_|  |_|  |_|

|¯| |¯|  |¯|  |¯|
|5| |6|  |7|  |8|
|_| |_|  |_|  |_|

|¯| |¯¯| |¯¯| |¯¯|
|9| |10| |11| |12|
|_| |__| |__| |__|

      <⍤1 m                  Enclose rows
|¯¯¯¯¯¯¯| |¯¯¯¯¯¯¯| |¯¯¯¯¯¯¯¯¯¯|
|1 2 3 4| |5 6 7 8| |9 10 11 12|
|_______| |_______| |__________|

gp    <⍤2 b                  Enclose matrices
|¯¯¯¯¯¯¯¯¯¯¯¯¯¯| |¯¯¯¯¯¯¯¯¯¯¯¯¯¯| |¯¯¯¯¯¯¯¯¯¯¯¯¯¯|
| 1  2  3  4  5| |21 22 23 24 25| |41 42 43 44 45|
| 6  7  8  9 10| |26 27 28 29 30| |46 47 48 49 50|
|11 12 13 14 15| |31 32 33 34 35| |51 52 53 54 55|
|16 17 18 19 20| |36 37 38 39 40| |56 57 58 59 60|
|______________| |______________| |______________|

Examples with Link

      v
1 2 3 4 5
      w
1 2 2 3 2

      v ⊃⍤0 w                Similar to (<⍤>v),[1.5] <⍤>w
|¯| |¯|
|1| |1|
|2| |2|
|3| |2|
|4| |3|
|5| |2|
|_| |_|

      m ⊃⍤1 n                Similar to (<⍤1 m),[1.5] <⍤1 n
|¯¯¯¯¯¯¯|    |¯¯¯¯¯¯¯|
|1 2 3 4|    |1 2 3 4|
|_______|    |_______|

|¯¯¯¯¯¯¯|    |¯¯¯¯¯¯¯|
|5 6 7 8|    |2 4 6 1|
|_______|    |_______|

|¯¯¯¯¯¯¯¯¯¯| |¯¯¯¯¯¯¯|
|9 10 11 12| |1 6 8 1|
|__________| |_______|

Examples with Grade

      n
1 2 3 4
2 4 6 1
1 6 8 1

      ⍋⍤1 n                  Upgrade each row independently
1 2 3 4 
4 1 2 3 
1 4 2 3

      ⍉ ⍋⍤1 ⍉n               Independent upgrade 
1 1 1 2                      of each column
3 2 2 3 
2 3 3 1

      q
abcde
edcba

      q ⍋⍤1 'abcdef'         Upgrade with multiple 
1 2 3 4 5 6                  collating sequences
5 4 3 2 1 6

An example with Ravel

   ,⍤2 b                     Ravel each matrix
 1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60

An example with Rotate

      (1-⍳4)⌽⍤1 2 b
 1  2  3  4  5
10  6  7  8  9
14 15 11 12 13
18 19 20 16 17

21 22 23 24 25
30 26 27 28 29
34 35 31 32 33
38 39 40 36 37

41 42 43 44 45
50 46 47 48 49
54 55 51 52 53
58 59 60 56 57

Examples with Catenate

      y
100 200 300

      y ,⍤0 2 b              Catenate scalars to matrices
100   1   2   3   4   5
100   6   7   8   9  10
100  11  12  13  14  15
100  16  17  18  19  20

200  21  22  23  24  25
200  26  27  28  29  30
200  31  32  33  34  35
200  36  37  38  39  40

300  41  42  43  44  45
300  46  47  48  49  50
300  51  52  53  54  55
300  56  57  58  59  60

      m ,⍤0 n                Same as m,[2.5] n
 1  1
 2  2
 3  3
 4  4

 5  2
 6  4
 7  6
 8  1

 9  1
10  6
11  8
12  1

Examples with Reshape

      5 4 ⍴⍤1 2 b            Reshape each plane
 1  2  3  4
 5  6  7  8
 9 10 11 12
13 14 15 16
17 18 19 20

21 22 23 24
25 26 27 28
29 30 31 32
33 34 35 36
37 38 39 40

41 42 43 44
45 46 47 48
49 50 51 52
53 54 55 56
57 58 59 60

      (5ׯ1↑⍴m) ⍴⍤1 m        Five side-by-side copies
1  2  3  4  1  2  3  4  1  2  3  4  1  2  3  4  1  2  3  4
5  6  7  8  5  6  7  8  5  6  7  8  5  6  7  8  5  6  7  8
9 10 11 12  9 10 11 12  9 10 11 12  9 10 11 12  9 10 11 12

Examples with Take

      7 ↑⍤1 m                Take on all rows;
1  2  3  4 0 0 0             the same as ((¯1↓⍴m),7)↑m
5  6  7  8 0 0 0
9 10 11 12 0 0 0

      ⍉ 7 ↑⍤1 ⍉ m            Take on all columns;
1  2  3  4                   the same as (7,1↓⍴m)↑m
5  6  7  8
9 10 11 12
0  0  0  0
0  0  0  0
0  0  0  0
0  0  0  0

      2 3 ↑⍤1 2 b            Take on each matrix
 1  2  3
 6  7  8

21 22 23
26 27 28

41 42 43
46 47 48

Examples with Match

      b ≡⍤1 ⊖b               Compare vectors
0 0 0 0
1 1 1 1
0 0 0 0

      b ≡⍤2 ⊖b               Compare matrices
0 1 0

Examples with Membership

      (⍳3) ∊⍤0 2 b           First scalar member of first
1 0 0                        plane, 2nd of 2nd plane, etc.

      (⍳7) ∊⍤1 2 b           Usual member of vector,
1 1 1 1 1 1 1                repeated for each matrix
0 0 0 0 0 0 0
0 0 0 0 0 0 0

Examples with Iota

      m
1  2  3  4
5  6  7  8
9 10 11 12

      n
1 2 3 4
2 4 6 1
1 6 8 1

      m ⍳⍤1 n                Independent search on rows;
1 2 3 4                      as in m[1;]⍳n[1;], etc.
5 5 2 5
5 5 5 5

      c←3 3⍴'keirbeeem'      Table lookup, as in ⎕io++/∧\d∨.≠⍉c
      d←2 3⍴'rbercm'
      (d∧.=⍉c)⍳⍤(1) 1
2 4 

Examples with Addition

      x
10 20 30 40

      x +⍤1 m                Add scalars to rows,
11 22 33 44                  as in, m+(⍴m)⍴x
15 26 37 48
19 30 41 52

      y
100 200 300

      ⍉ y+⍤1 ⍉m              Add scalars to columns
101 102 103 104              as in,m+⍉(⌽⍴m)⍴⍉y
205 206 207 208
309 310 311 312

      y +⍤0 2 b              Add scalars to matrices
101 102 103 104 105
106 107 108 109 110
111 112 113 114 115
116 117 118 119 120

221 222 223 224 225
226 227 228 229 230
231 232 233 234 235
236 237 238 239 240

341 342 343 344 345
346 347 348 349 350
351 352 353 354 355
356 357 358 359 360

An example with Representation

      10 10⊤v
0 0 0 0 0
1 2 3 4 5

      10 10 ⊤⍤1 0 v          A different representation
0 1
0 2
0 3
0 4
0 5

Domains of Operators , , ¨

The left argument of the operators , , ¨ may be any primitive function except execute (). The valid right arguments ofinclude any scalar or vector of integers containing at most three elements.

A primitive function g is a valid right argument ofand(and of ¨ if it has an assigned inverse) if its relevant ranks (left and right in the case of ⍺ f⍥g ⍵ , and monadic in all other cases) have been assigned. The following table shows function ranks, denoting infinite rank by ¯ , and unassigned rank by :

 ⌹  <  >  ⍴  ,  ⍉  ∊  ⍋  ⍒  ?  ⊤  ⍕  ≡  ⊢  ⊣  ⊃     Function
 2  ¯  0  ¯  ¯  ¯  ⍝  ¯  ¯  0  ⍝  ¯  ⍝  ¯  ¯  ¯     Monadic
 ¯  0  0  ⍝  ¯  ⍝  0  ¯  ¯  ⍝  ¯  ⍝  ¯  ¯  ¯  ¯     Left
 2  0  0  ⍝  ¯  ⍝  ¯  ¯  ¯  ⍝  ¯  ⍝  ¯  ¯  ¯  ¯     Right

The functions ⊥ ⍳ ⌽ ⊖ ↑ ↓ ⍎ are not included in this table because their ranks have not been assigned.

All scalar primitive functions have rank 0 and are therefore in the right domains ofand . A monadic function g is in the right domain of ¨ if it is in the right domain ofand also occurs in the following table of assigned inverses:

 +  -  ÷  *  ~  <  ⍉  ⊢  ⌹ > ⍟ Function
 +  -  ÷  ⍟  ~  >  ⍉  ⊢  ⌹ < * Inverse

Levand Dex

Definition:

The dyadic functions Levand Dex return their left and right arguments, respectively. Each symbol points toward the argument it returns. The names are derived form the Latin words meaning ‘on the left side’ (laevus) and ‘on the right side’ (dexter).

The monadic case ofis an identity function. It returns its argument unchanged. The monadic case ofreturns no result, and is thus equivalent to ⍎'' . ⊣a will work, but z←⊣a will give a result error . Both cases of each function have infinite rank, and thus can be used with the operators On, Over, and With.

Application:

A) Many system functions both cause side effects (like defining functions) and return explicit results. If the result is not needed, it can be discarded using Lev. For example, the statement

[∘]  junk←⎕ex namelist

can also be written as

[∘]  ⊣⎕ex namelist

B) Lev, when used dyadically, provides a statement connection facility. Unlike diamond, the statement on the right side of the Lev function will execute first.
 

Link

Definition:

The monadic functionis a conditional enclose. If the argument is simple (not enclosed), then it is enclosed. If the argument is non-simple, it is returned unchanged.

The dyadic functionis called Link. It encloses its left argument, applies the conditional enclose to the right argument, and catenates the results. These rules can be summarized by the following.

⊃⍵  ←→ <⍵ ifis simple
  ←→ ifis non-simple
 
⍺⊃⍵ ←→ (<⍺),⊃⍵ 

Both cases ofhave infinite rank, enabling it to be used as the right function argument in composition. Note that in the expression ⍺⊃⍵ , the symbol (like the symbol < in <⍵ ) opens toward the argument to be enclosed.

If the right argument () is simple, the shape of the result will always be 2. If the right argument () is not simple, the shape of the result will be ((-⍴⍴⍵)↑1)+⍴⍵ . This is due to the scalar extension of the left argument when the catenation occurs. The following example illustrates this point.

      ⎕ps←-1 1 3 3
      g←2 5⍴'0123456789'
      h←<⍤(0) 3 4⍴'abcdefghijkl'
      ⍴h⊃g
2
      h⊃g
|¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯| |¯¯¯¯¯|
||¯| |¯| |¯| |¯|| |01234|
||a| |b| |c| |d|| |56789|
||_| |_| |_| |_|| |_____|
|               |
||¯| |¯| |¯| |¯||
||e| |f| |g| |h|| 
||_| |_| |_| |_||
|               |
||¯| |¯| |¯| |¯||
||i| |j| |k| |l|| 
||_| |_| |_| |_||
|_______________|

      ⍴g⊃h
3 5
      g⊃h
|¯¯¯¯¯| |¯| |¯| |¯| |¯|
|01234| |a| |b| |c| |d|
|56789| |_| |_| |_| |_|
|_____|  

|¯¯¯¯¯| |¯| |¯| |¯| |¯|
|01234| |e| |f| |g| |h|
|56789| |_| |_| |_| |_|
|_____|  

|¯¯¯¯¯| |¯| |¯| |¯| |¯|
|01234| |i| |j| |k| |l|
|56789| |_| |_| |_| |_|
|_____|  

Application:

A) Monadiccan be used to test whether an array is simple.

simple⋄ ~⍵≡⍵

B) Dyadiccan be used to create enclosed arrays without having to explicitly enclose and catenate the elements.

OLD WAY       NEW WAY
(<1 2),(<'def'),<6 7 8 9  1 2⊃'def'⊃6 7 8 9

Note that the new way is more readable and uses fewer functions.
 

Matrix Inverse and Matrix Division

Definition:

In the past, the functions denoted bywere limited to working with arguments whose rank was less than or equal to 2. The definition of Matrix Inverse is still based on inverting rank 2 arrays. But now, it can be applied to multiple matrices in a single operation, rather than by looping.

Old Way   New Way
z[1;;]←⌹x[1;;] z←⌹x
z[2;;]←⌹x[2;;]
z[3;;]←⌹x[3;;] ....

This example shows that the new Matrix Inverse function inverts the matrices along the last two axes of the argument.

Since Matrix Division is defined in terms of Matrix Inverse ( ⍺⌹⍵ ≡ (⌹⍵)+.×⍺ ) its definition is extended in a similar manner.

The rules for determining the argument and result shapes are given below. (The degenerate cases where 2>⍴⍴⍵ work as before and are not included in this table.)

Function ⍴⍵    ⍴⍺   ⍴z
z←⌹⍵ (1↑¯2↑⍴⍵)≥¯1↑⍴⍵  - (¯2↓⍴⍵),⌽¯2↑⍴⍵
z←⍺⌹⍵ (1↑¯2↑⍴⍵)≥¯1↑⍴⍵  (1↑⍴⍺)=1↑¯2↑⍴⍵ (¯2↓⍴⍵),(¯1↑⍴⍵),1↓⍴⍺

Application:

To solve several systems of equations which have different coefficients, but the same constants, try an expression like the following.

constantvector⌹coeffmatrix1,[0.5] coeffmatrix2

To solve several systems of equations which have the same coefficients, but different constants, try an expression like the following.

(constantvector1,[1.5] constantvector2)⌹coeffmatrix

Examples:

      a←2 2 2⍴0 1 1 2 3 5 8 13
      ⌹a
 ¯2  1
  1  0

¯13  5
  8 ¯3
      b←2 2⍴1 0 0 1
      b⌹a
 ¯2  1
  1  0

¯13  5
  8 ¯3
      c←2 3 4⍴⍳24
      c⌹a
 11  10   9   8
  7   6   5   4
  3   2   1   0

  1   2   3   4
  5   6   7   8
  9  10  11  12


 52  44  36  28
 20  12   4  ¯4
¯12 ¯20 ¯28 ¯36

¯31 ¯26 ¯21 ¯16
¯11  ¯6  ¯1   4
  9  14  19  24

Acknowledgements: The following people contributed to this SATN: R. Bernecky, K.E. Iverson, E.E. McDonnell, R.C. Metzger, J.H. Schueler.



Errata

  In the Examples section, q should be initialized to 2 5⍴'abcdeedcba' .
  In the Examples with Enclose section, there should not be a gp in the last example.


First appeared as SHARP APL Technical Note 45, Language Extensions of May 1983, 1983-05-02.

created:  2009-11-08 22:35
updated:2014-10-15 13:20