Search Top Index
HELP IN_ARRAY David Young, January 1994 This * FOR_FORM is used for looping over data in arrays. CONTENTS - (Use <ENTER> g to access required sections) 1 Introduction 2 Basic use 3 Additional facilities 3.1 with_index 3.2 updating_last 3.3 in_region 3.4 of_dimension 4 One-D equivalence and optimisation 5 fast_for form ----------------------------------------------------------------------- 1 Introduction ----------------------------------------------------------------------- The * FOR_FORM for ... in_array ... do ... endfor allows looping over the data in arrays (see REF * ARRAYS), much as other forms allow looping over data in lists and vectors. This can often replace a number of nested numerical for loops, and provide greater flexibility in programs that deal with arrays with varying numbers of dimensions. The general in_array form includes several components: for var1, var2, ... with_index ivar in_array array1, array2, ... updating_last n in_region list of_dimension d do ... endfor Any of the with_index, updating_last, in_region and of_dimension components may be omitted. They may be included in any combination, as long as they are in the order shown above. It is also possible to iterate a set of coordinates over an N-dimensional region using for ivar in_region list do ... endfor See HELP * in_region for more details of this. ----------------------------------------------------------------------- 2 Basic use ----------------------------------------------------------------------- The simplest usage is for var1, var2, ... in_array array1, array2, ... do Each of the variables varN iterates over elements of the corresponding array arrayN. The arrays must all have the same number of dimensions. If their boundslists differ, iteration occurs over the elements that they have in common. E.g., if the boundslists are [0 100 1 10] and [50 150 0 5] then the loop runs over elements whose first index takes values from 50 to 100 and whose second takes values from 1 to 5. Array elements are processed in order, with the first index increasing most quickly. For example, a 2-D array containing pairs, each of which contains its own indices in the array, can be made with: vars array1; newarray([1 3 1 2], conspair) -> array1; Printing out the values of this array with vars v1; for v1 in_array array1 do v1 => endfor; gives ** [1|1] ** [2|1] ** [3|1] ** [1|2] ** [2|2] ** [3|2] ----------------------------------------------------------------------- 3 Additional facilities ----------------------------------------------------------------------- The following constructs can be included in any combination, as long as they are in the order shown at the top of this file. The examples show only each one added to the basic format on its own. 3.1 with_index --------------- The current indices into the arrays can be kept track of using for var1, ... with_index ivar in_array array1, ... do The variable ivar is assigned a vector whose length is equal to the number of dimensions of the arrays. During execution of the loop, the contents of the this vector are the current indices into the array. That is, when ivar has the value {c1, c2 , ...}, the value of arrayN(c1, c2, ...) is assigned to varN. The code in the body of the loop should not assign anything to ivar, and should not change the contents of the vector. If it is necessary to save the indices at some point and continue the loop, the vector must be copied and not just assigned to another variable. One way to update an array inside the loop is to use an index variable - applying destvector to it will give the indices to use for updating the current array element. However, it is more efficient (and neater) to use the facility described next, particularly if having an index variable can then be avoided. 3.2 updating_last ------------------ Updating an array can be done with for var1, ... varp in_array array1, ... arrayp updating_last do The value of the last variable varp is then used to update the last array arrayp. This happens at the end of the loop, in effect just before the endfor is reached, but after all the code in the body of the loop has executed. This variable varp is not assigned a value automatically like the other loop variables; it is up to the code in the body of the loop to give it a value. For example, the following code adds 1 to every element in array1, storing the results in array2. for v1, v2 in array1, array2 updating_last do v1 + 1 -> v2 endfor An array can be specified twice if it is both to supply and receive values. An integer n may be placed after updating_last to specify that the last n arrays are to be updated from the last n variables. for var1, ... in_array array1, ... updating_last n do Note that n must be given as an integer (or a macro that expands to an integer) in the program, not as an expression or variable. All the variables can be update variables if the purpose of the loop is to fill arrays or parts of them with data from some other source. 3.3 in_region -------------- It is possible to specify explicitly the region of the arrays over which to iterate, with a list in the form of a *boundslist. The syntax is for var1, ... in_array array1, ... in_region list do The first index into the arrays takes values between the first two numbers in list, inclusive; the second index takes values between the next two numbers; and so on. The region specified by list can be pictured as rectangular for 2-D arrays and cuboid for 3-D arrays. The region must not include any elements which cannot be accessed in all the arrays. The form for ivar in_region list do is also available if only the coordinates are required. This has the same effect as for with_index ivar in_array in_region list do would have if it was possible to omit all the arrays from the in_array form (which it isn't). See HELP * in_region for more details. 3.4 of_dimension ----------------- If the number of dimensions of the arrays is known in advance (when the loop is compiled) then of_dimension can be used: for var1, ... in_array array1, ... of_dimension d do Here d must be an integer in the program (or a macro that expands to an integer), not an expression or variable. The arrays must all have d dimensions. The main effects of this are to produce more compact code and reduce the startup time for the loop. For most applications, it is not likely to be worth bothering with of_dimension, even if the dimensionality is known at compile time. It may be worth including if EITHER the code must be as small as possible; OR the code must run as fast as possible AND the dimensionality is 3 or greater AND EITHER the user index (with_index) is used OR the arrays are not all 1-D equivalent (see below) OR the code must run as fast as possible AND the arrays or region will be very small AND it is possible to use the fast_for form (see below) Including of_dimension may cause a slight slow-down in the case of 1-D arrays, or where 1-D optimisation (see below) would otherise get done. For small regions, this might be balanced by a decrease in start-up overhead. ----------------------------------------------------------------------- 4 One-D equivalence and optimisation ----------------------------------------------------------------------- Most programmers can ignore this section, which is provided for completeness, and to explain the reasons behind the indications for using of_dimension, given above. An array is 1-D equivalent with respect to a region if the data referenced by indices in that region are stored in a contiguous section of the arrayvector. In addition, the array must be either actually 1-D or arrayed by row (REF * ARRAYS). Thus, for example, all by-row arrays are 1-D equivalent with respect to their own boundslists. It is often faster to access a 1-D equivalent array via a single index into its arrayvector, rather than by applying the array procedure to multiple indices. The single index also involves fewer increment-and-test operations in the loop. This can greatly reduce the loop overhead, at the expense of slightly increased start-up time and code size. This optimisation is never done if the number of dimensions has been specified at compile-time using of_dimension. Otherwise, it is carried out if either the arrays are actually 1-D or all the arrays are 1-D equivalent with respect to the processing region, and no index variable has been specified using with_index. (The processing region is either the region specified using in_region or the intersection of the boundslists of the arrays.) ----------------------------------------------------------------------- 5 fast_for form ----------------------------------------------------------------------- If fast_for is used instead of for, initial checks on the arrays and region are not carried out. As usual with fast loop forms, strange behaviour will result if assumptions are violated, e.g. if the arrays have different numbers of dimensions, or the region is not within all the array bounds. In addition, if in_region is not specified, the boundslist of the first array is used as the region, rather than the intersection of all the boundslists. --- C.all/help/in_array --- Copyright University of Sussex 1994. All rights reserved.