Indexing Questions

Topics in this section include:

From: (Jim Weigang)
Newsgroups: comp.lang.apl
Date: 5 Jan 1995 05:40:36 GMT
Subject: Re: Assigning numbers to a matrix

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:


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.


From: (Jim Weigang)
Newsgroups: comp.lang.apl
Date: 22 May 1995 13:53:23 GMT
Subject: Re: "Each" operator in APL+III for Windows

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:


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):


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}.


From: (Jim Weigang)
Newsgroups: comp.lang.apl
Date: 31 May 1995 01:28:31 GMT
Subject: Re: indexing

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 X

What 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:

      J{<-}(3 2 1) (4 5) 6

1 0 0 1 0 1

      V{<-}B{enclose}[1]M[{enlist}J;]      @ #IO=1


 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