Topics in this section include:

- How to index scattered points in a matrix
- How to apply the each operator to indexing
- How to index with a nested vector of indices

Ralph Schiller wrote:

Suppose you have a matrix A of dimension [m,n]. Then there is a wonderful opportunity to get the numbers A[i,k] if you have a set of indices using the Squash quad. Now my question is whether there is a short way of assigning a number (or a set of numbers) to a given set of indices of the matrix.

Scattered points in a matrix can be selected or assigned by raveling the
matrix and using indices J which pick the same elements of the vector as
`A[Row;Col]` picks in the matrix. Here's an assignment example:

V{<-},A V[J]{<-}NewData A{<-}({shape}A){reshape}V

The vector indices J can be computed from the row and column indices in several ways. You can use explicit arithmetic:

J{<-}Col+(Row-1){times}1{drop}{shape}A @ #IO=1 J{<-}Col+Row{times}1{drop}{shape}A @ #IO=0

Or you can use base value, as in:

J{<-}1+({shape}A){basevalue}{neg}1+Row,[.5]Col @ #IO=1 J{<-}({shape}A){basevalue}Row,[{neg}.5]Col @ #IO=0

The base value technique can be used to index scattered points in an N-dimensional array. In general, the right argument to base value should be an array whose first dimension has length N, the rank of A. In the 3-D case, the levels of the first dimension should hold the plane, row, and column indices, in that order.

These techniques work on all APL systems and are reasonably
efficient. Selective assignment is a nifty alternative, but it should
be used with some caution. For example, if you have a million-element
Boolean vector, `B[1]{<-}X` takes practically no time to
execute, but `(1{take}B){<-}X` is quite slow. The reason?
This selective assignment statement is executed (at least on some
systems) as `B[1{take}{iota}{shape}B]{<-}X`, and creating
`{iota}1000000` takes a while.

On 20 May 1995, Steve Forsythe wrote:

I would like to apply the "each" operator (for distributing an operation over a pair of vectors) to the subscripting operation.

You can't apply each to bracket indexing. Depending on what you want to do, you might need to define a cover function that you can use with each. But bear in mind that each is a relatively slow operation, and that applying it to a user-defined function is roughly equivalent to writing a loop.

It sounds like you are trying to do "scattered-point selection", i.e., select elements at arbitrary locations within a matrix. For example, if M is the 3-by-5 matrix:

ABCDE FGHIJ KLMNO

and you want to select D and L, you can use `M[(1 4)(3 2)]`. If
the row and column indices are in variables (e.g., `ROW{<-}1
3` and `COL{<-}4 2`), you can use (with `#IO=1`):

M[ROW,{each}COL] (,M)[COL+(1{drop}{rho}M){times}ROW-1] (,M)[1+({rho}M){basevalue}{neg}1+ROW,[.5]COL]

The last two expressions will work in any APL, and the final expression can be generalized to index arbitrary elements in an N-dimensional array.

These alternatives have rather different execution times. For 1000-element ROW and COL vectors, the run times on a 486/66 using APL*PLUS II/386 v5.2 were:

Secs Expression ----- ----------------------------- 0.613 ({enclose}M)NDX{each}ROW,{each}COL where NDX:{alpha}[{omega}[1];{omega}[2]] 0.082 M[ROW,{each}COL] 0.003 (,M)[COL+(1{drop}{rho}M){times}ROW-1] 0.007 (,M)[1+({rho}M){basevalue}{neg}1+ROW,[.5]COL]

The third expression is fully 200 times faster than NDX{each}.

Jim

On 30 May 1995, Ed Shaw wrote:

I have the need to create a nested vector of matrices. [...]

e.g., M is 25 30 reshape 'sfjjsdflk........' X is (1 3 5 7)(8 4 5 14)(18 4 8 12 22 5) R is vector of nested matrices with rows of M, specified by XWhat I thought might work, but doesn't, is R is M[X;]

Use partitioned enclose. Unfortunately, this is one of the not-well- standardized extended-APL features, and I'm not sure what Dyalog APL has available. In APL*PLUS II or III, you can use:

M{<-}VTOM' ONE TWO THREE FOUR FIVE SIX' M ONE TWO THREE FOUR FIVE SIX J{<-}(3 2 1) (4 5) 6 B{<-}{enlist}({shape}{each}J){take}{each}1 B 1 0 0 1 0 1 V{<-}B{enclose}[1]M[{enlist}J;] @ #IO=1 V THREE FOUR SIX TWO FIVE ONE {shape}V 3 {shape}{each}V 3 5 2 5 1 5

If `{enlist}` isn't available, use "`{disclose},/`"
instead. By the way, this is a situation in which the nested technique
beats out the eachless looping version. For a 1000-element J, the
technique above runs in about 0.14 secs; the looping version takes 3.55
secs (on a 486/66, APL*PLUS II v5.2).

Home Page