A+ Reference: Dyadic Operators

# Dyadic Operators

Common Error Reports
Definitions of Dyadic Operators

Inner Product y f.g x
Outer Product y Ê.f x
Rank f@n x and y f@n x

Rank Operator uses Frames and Cells
The Rank Operator and Empty Arguments
Rank Deriving Monadic f@n x
Rank Deriving Dyadic y f@n x

# Common Error Reports

> Multiple errors elicit but one report. If an error report in the following list is issued, then the ones preceding it do not apply. Five reports are common to all dyadic operators:

> - parse;
> - value: an argument has no value;
> - nondata: an argument (not an operand) is a function or some other nondata object;
> - an error report from an operand function;
> - wsfull: the workspace is currently not large enough to execute the function in; a bare left arrow (û), which dictates resumption of execution, causes the workspace to be enlarged if possible;
> - interrupt (not an error): the user pressed c twice (once if A+ was started from a shell) while holding the Control key down.

# Definitions of Dyadic Operators

## Inner Product y f.g x

Arguments and Result

> There are three inner products in A+: +.«, Ó.+, and Ä.+. The arguments y and x must be nonscalars, and ¢1ÙÒy must equal 1ÙÒx. The shape of the result is (¢1ÕÒy),1ÕÒx.

Definition

> For matrices y and x, the function g is applied to row vectors of y on the left and column vectors of x on the right, in all combinations; f/ is applied to each these results. That is:

>           (y f.g x)[i;j] ûý f/y[i;]g x[;j]

> for all scalar indices i and j. The general definition of +.« is:

>          y (pdt@1 1 0)(¢1÷ÉÒÒx)ôx

> where

>          a pdt b:+/a«b

> The function pdt must be applied to vectors along the last axis of y and vectors along the first axis of x, in all combinations. In order to do this with the Rank operator, the vectors along the first axis of x must be moved to the last axis. The expression (¢1÷ÉÒÒx)ôx has the effect of moving the first axis of x to the last, while leaving all other axes in their original order.

> Analogous definitions hold for Ó.+ and Ä.+.

> As pointed out in "Operators and Derived Functions", Inner Product is not in the strictest sense an operator, but for most purposes it can be regarded as one.

Additional Error Reports

> Each of the following reports is issued only if there is no parse or value error report (see "Common Error Reports") - the token report preceding the value report -, and none of the reports preceding it on this list applies:

> - a token error is reported if f or g is a defined function name or a primitive function or operator symbol such that the derived function is not one of the three permitted forms;
> - a valence error is reported if there is no left argument for the derived function (a missing right argument is a parse error);
> - a rank error is reported if one of the arguments is a scalar;
> - a length error is reported if the last dimension of y and the first dimension of x are not equal.

Example

>          (É2 3)+.«(É3 4)
>      20 23 26 29
>      56 68 80 92

## Outer Product 1 y Ê.f x

Arguments and Result

> f can be one of +, «, -, ß, Ó, Ä, |, <, ¤, =, ¦, >, ¨, and *. The arguments y and x are any arrays whose elements are suitable left and right arguments of f, respectively. The shape of the result is (Òy),(Òx).

Definition

> The function f is applied to all combinations of scalars from y and x. In particular, for vectors x and y:

>          (yÊ.f x)[i;j] ûý y[i]f x[j]

> for all scalar indices i and j. Similar relations hold for arrays of other ranks. In general, yÊ.f x is equivalent to y(f@0 0 0)x.

> As pointed out in the "Operators and Derived Functions", Outer Product is not in the strictest sense an operator, but for most purposes it can be regarded as one.

Additional Error Reports

> If there is no error reported as a parse error, then a similar error may be reported:

> - a token error is reported if f is a defined function name or a primitive function or operator symbol such that the derived function is not one of the permitted forms.
> The following report is issued only if there is no parse, token, or value error (see "Common Error Reports"):

> - a valence error is reported if there is no left argument for the derived function (a missing right argument is a parse error).

Example

>          1 10 100Ê.«1.2 ¢3 98.2 5
>        1.2   ¢3     98.2    5
>       12    ¢30    982     50
>      120   ¢300   9820    500

## Rank f@n x and y f@n x

> (Just as for all operators, f cannot be Assignment.) Rank's derivation of monadic functions and its derivation of dyadic functions are covered in separate sections below. First, however, you should understand how the operator decomposes arrays, and the implications for its handling of empty arrays.

### Rank Operator uses Frames and Cells

> The Rank operator (f@n x and y f@n x) splits an array into equal-shaped cells held in a frame and applies its function to each cell. The frame's shape consists of zero or more leading dimensions of the array and the cells' shape consists of the remaining zero or more trailing dimensions. (Cf. "Dimension, Shape, and Rank".) Rank deriving dyadic splits each argument separately.

> For example, a function applied to an array of shape 3 4 5 using the Rank operator may be applied to:

> - cells of shape É0 (scalar) in a frame of shape 3 4 5; or
> - cells of shape 5 in a frame of shape 3 4; or
> - cells of shape 4 5 in a 3-item frame; or
> - a single cell with shape 3 4 5 in a frame with shape É0 (scalar).
> Rank allows specification of the rank of either the cells (a positive number in n) or the frame (a negative number in n, whose magnitude is used). For example, to have the Rank operator apply a function to rank-2 cells in a 3-dimensional array, you can use either 2 (for the rank of each cell) or -1 (for a frame rank of 1).

> If |n exceeds the rank of an argument to which it is applied, it is treated as if it equaled that rank. Thus you can specify both extreme cases in a way independent of rank: to allot all the axes to the frame, you specify cell rank to be 0, of course; to give all axes to the cells, you specify cell rank to be 9, the limit on ranks.

### The Rank Operator and Empty Arguments

> The shape of the result of the derived function is always determined in the same way (with any additional axes on the right produced by the operand function), whether the arguments are empty or not. The type of the result, however, is a different matter. In the absence of an empty frame, the type is determined by the operand function, for the empty cells. On the other hand, if a frame is empty, the Rank operator never calls this function. For a primitive function, Rank uses its result type, or at least its default result type. For a nonprimitive function, it uses null. These examples show this type selection:

>          y f x:x     ã A simple function to be used as an operand.

>          ©2(f@1)É0   ã Scalar frames, empty-vector cells (left argument is made
>      `int            ã to conform to right). An empty integer vector is returned
>                      ã to Rank by f.

>          ©2(f@0)É0   ã An empty-vector frame (from right argument); no (scalar)
>      `null           ã cells for f, so no call. Rank makes the result type null.

>          ©2(+@1)É0   ã Like the first example.
>      `int            ã +É0 is integer.

>          ©2(+@0)É0   ã Rank doesn't apply Add to anything, but does use the type
>      `int            ã implied by Add: the Add result type for integers is integer,
>                      ã if the result can be so represented.

>          (É0) ß@0 É0 ã Rank passes fake args (the usual zeros, unhappily)
>      ß: domain       ã to the operand function to determine the size and
>                      ã type of the result. Divide is not amused.

### Rank Deriving Monadic f@n x

> The rank specification n is a one-element integer array. For conformity with the discussion of Rank deriving dyadic, assume n is a vector. Then if n is nonnegative, Rank applies f to cells of rank jûn[0]ÄÒÒx within a frame of shape (-j)ÕÒx.

> If n is negative, Rank applies f to cells of rank kû0Ó(ÒÒx)-|n[0] within a frame of shape (-k)ÕÒx.

Additional Error Reports

> Each of the following reports is issued for Rank deriving monadic only if there is no parse or value error (see "Common Error Reports") and none of the reports preceding it on this list applies:

> - a type error is reported if n is not a simple integer array;
> - a length error is reported if n has more than 3 elements (although only the first element is used);
> - a nonfunction error is reported if f is not a function.

Examples

>          (+/@1) 2 3Ò10 20 30 1 2 3 ã The data operand must be separated
>      60 6              ã from the left argument of Reshape: parentheses used.

>          ÷@¢1 É2 3 4   ã The frame is of rank 1, so the cells are of rank 2.
>       8  9 10 11       ã ÷ is called twice, with matrices as arguments,
>       4  5  6  7       ã so the items whose order is reversed by
>       0  1  2  3       ã ÷ are rows.

>      20 21 22 23
>      16 17 18 19
>      12 13 14 15

>          ÷@1 É2 3 4    ã The cells are of rank 1, so the frame is of rank 2.
>       3  2  1  0       ã ÷ is called six times, with rows as arguments,
>       7  6  5  4       ã so the items whose order is reversed by
>      11 10  9  8       ã ÷ are scalars.

>      15 14 13 12
>      19 18 17 16
>      23 22 21 20

>          ÷@3 É2 3 4    ã The cells are of rank 3, so the frame is scalar.
>      12 13 14 15       ã ÷ is called just once, with a rank-3 array as arg,
>      16 17 18 19       ã so the items whose order is reversed by
>      20 21 22 23       ã ÷ are matrices.
>                        ã ÷@3 É2 3 4 is equivalent to ÷É2 3 4
>       0  1  2  3
>       4  5  6  7
>       8  9 10 11

### Rank Deriving Dyadic y f@n x

> The rank specification n must be an integer array with one, two, or three elements. For convenience, assume n is a vector throughout this description.

> There are three behaviors for Rank deriving dyadic, depending upon n;

> - when n has one or two elements, Rank deriving dyadic bears some similarity to a scalar dyadic function: the resulting frames on x and y must be the same shape after any deficiency in the rank of one of them is made up by replication (a very permissive scalar extension), and the operand function is applied to pairs of corresponding cells;

> - when n has a third element of zero, the operator bears a similarity to Outer Product: the operand function is applied to pairs of cells in all possible combinations;

> - when n has a nonzero third element, the operator bears some similarity to a scalar dyadic function on the trailing n[2] axes of the frames and a similarity to Outer Product on the remaining (leading) axes of the frames (but see below for the subtleties glossed over here).
> If n has one element and is nonnegative, Rank applies f to cells of rank jûn[0]ÄÒÒx within a frame of shape (-j)ÕÒx on x and to cells of rank kûn[0]ÄÒÒy within a frame of shape (-k)ÕÒy on y.

> If n has one element and is negative , Rank applies f to cells of rank jû0Ó(ÒÒx)-|n[0] within a frame of shape (-j)ÕÒx on x and to cells of rank kû0Ó(ÒÒy)-|n[0] within a frame of shape (-k)ÕÒy on y. A common case is f@¢1 (which pairs items from both arguments and applies the function f to each pair).

> If n has two elements, then the first element of n is used for y and the second element is used for x, each interpreted in the same way as when n has one element.

> When n has three elements, the first two are used in the manner just stated. The third element of n breaks the frame into two subframes, leading and trailing. It specifies the number of trailing axes in the frames of x and y in which cells will be paired with corresponding cells, and in which, therefore, mismatched dimensions are forbidden. Any leading dimensions present in one trailing subframe and absent in the other - which must in this case be a whole frame -, are supplied by replicating the latter subframe. Any remaining (leading) axes of the frames are used to create subframes whose members are paired in all possible ways, in the manner of an outer product. Again, n can be excessive; any excess is dealt with as described in the next paragraphs.

> Assume, just for convenience, that the first two elements of n are positive. Set
> cyûn[0]ÄÒÒy and cxûn[1]ÄÒÒx (cell ranks), tyûn[2]Ä(ÒÒy)-cy and txûn[2]Ä(ÒÒx)-cx (ranks of the trailing parts of the frames), and lyû0Ó(ÒÒy)-cy+ty and lxû0Ó(ÒÒx)-cx+tx (ranks of the leading parts of the frames).

> That is, the cell specifications are honored to the extent possible, then the trailing subframe specification is honored to the extent possible, and the leading subframes are whatever is left. The function f is applied to pairs of cells of rank cy and cx taken from y and x respectively, using all combinations of subscripts for the first ly and lx axes and corresponding subscripts for the next tyÓtx axes (after possible replication of one trailing subframe to make these subframes match).

> Whether the cells match is the responsibility of the operand function. The two leading subframes have no compatibility requirement. The two trailing subframes must match only as far as they both exist: specifically,

>          (-tyÄtx)Ù(-cy)ÕÒy  ûý  (-tyÄtx)Ù(-cx)ÕÒx.

> Clearly, if ty is less than tx (and so the trailing subframe for y is replicated to match the shape of the trailing subframe for x), then ly is zero, and if tx is less than ty, then lx is zero.

>     Note that:
>     if n has only one element, y (f@n) x is equivalent to y (f@ n,n) x
>             which is equivalent to y (f@ n,n,9) x
>     and if n has exactly two elements, y (f@n) x is equivalent to y (f@ n,9) x.
>     When n has fewer than three elements, the trailing subframes are simply the frames.

Additional Error Reports

> Each of the following reports is issued for Rank deriving dyadic only if there is no parse or value error (see "Common Error Reports") and none of the reports preceding it on this list applies:

> - a type error is reported if n is not a simple integer array;
> - a length error is reported if n has more than 3 elements;
> - a mismatch error is reported if the shapes of the subframes do not match;
> - a nonfunction error is reported if f is not a function.

Examples

>          '-->' ,@1 Û4!'abcdABCD' ã Rank 1 cell (rank 0 frame) vs. rank 1
>      -->abcd                     ã cell (rank 1 frame). The scalar left
>      -->ABCD                     ã frame is treated as a 2-element vector.

>          '01' ,@¢1 Û4!'abcdABCD' ã Rank 1 frame (rank 0 cell) vs. rank 1
>      0abcd                       ã frame (rank 1 cell).
>      1ABCD

>          (É3)(,@0 1)É2 3 4       ã Rank 0 cell (rank 1 frame) vs. rank 1
>        0  0  1  2  3             ã cell (rank 2 frame). The vector left
>        1  4  5  6  7             ã frame is treated as a 2 by 3 matrix: the
>        2  8  9 10 11             ã "missing" dimension is supplied.

>        0 12 13 14 15
>        1 16 17 18 19
>        2 20 21 22 23

>          (1990+É2)(,@0 1 0)É2 3  ã Both left argument scalars vs.
>      1990    0    1    2         ã both right argument vectors. Cells left
>      1990    3    4    5         ã rank 0, right rank 1; rank 0 trailing
>                                  ã subframes and rank 1 leading subframes
>      1991    0    1    2         ã for both.
>      1991    3    4    5

>          (É2 3 4),@1 1 2(É2 3 9) ã Vector vs. vector, rank 0 leading
>        0  1  2  3  0  1  2  3  4  5  6  7  8  ã subframes. The
>        4  5  6  7  9 10 11 12 13 14 15 16 17  ã 1 1 2 operand
>        8  9 10 11 18 19 20 21 22 23 24 25 26  ã  could as well be
>                                               ã 1 1
>       12 13 14 15 27 28 29 30 31 32 33 34 35
>       16 17 18 19 36 37 38 39 40 41 42 43 44
>       20 21 22 23 45 46 47 48 49 50 51 52 53

> Now vector cells, from corresponding rows, both planes vs. both planes (rank 1 cells, rank 1 trailing subframes, and rank 1 leading subframes for both). The arguments are:

>          2 3 3Ò"my you it  t hedog"
>     my
>     you
>      it

>       t
>      he
>     dog

>     and

>          2 3 4Ò"hat  did is win rs  's  "
>     hat
>      did
>      is

>     win
>     rs
>     's

> Applying ,@1 1 1 to them yields

>          (2 3 3Ò"my you it  t hedog")(,@1 1 1
>     *     )2 3 4Ò"hat  did is win rs  's  "
>     my hat
>     you did
>      it is
>     my win
>     yours
>      it's

>       that
>      he did
>     dog is

>       twin
>      hers
>     dog's

Errors

> Errors may be reported by either the operator or an operand:

>          (É2 4 4),@1 1(É2 3 9)  ã One trailing subframe a vector of length
>     ,@1: mismatch               ã four, the other a vector of length three.
>     *     ý                     ã Rank notes the discrepancy in lengths.

>          (É24)(+@0)É23
>     +@0: mismatch               ã Rank can't pair scalar cells for Add.
>     *     ý

>          (É24)(+@1)É23          ã Rank can pair vector cells for Add,
>      +: length                  ã but Add can't pair scalar items.
>     *      ý

Inner and Outer Products

> If there is no Outer Product for f, f@0 0 0 may be used.
> Sine, cosine, tangent of 0 45 90 ... 360 degrees, with the result doctored to show Inf:

>          8.4î 1 2 3 Ï@0 0 0 Ï.25«É9
>       0.0000  0.7071  1.0000  0.7071  0.0000 -0.7071 -1.0000 -0.7071  0.0000
>       1.0000  0.7071  0.0000 -0.7071 -1.0000 -0.7071  0.0000  0.7071  1.0000
>       0.0000  1.0000     Inf -1.0000  0.0000  1.0000    ¢Inf -1.0000  0.0000

> If there is no Inner Product for f and g, f/@(ÒÒy) x g@0 ¢1 y may be used (if there is no Reduction for f a defined reduction operator may be used). For (É2 12)^.<É12 24:

>          ^/@2 (É2 12) <@0 ¢1 É12 24
>      0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
>      0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1