Pascal Array Assignment Operator

On By In 1

Vector Pascal, an array language

Paul Cockshott, University of Glasgow, Imaging Faraday Partnership
Greg Michaelson, Heriot Watt University

Abstract

Vector Pascal is a language designed to support elegant and efficient expression of algorithms using the SIMD model of computation. It imports into Pascal abstraction mechanisms derived from functional languages having their origins in APL. In particular it extends all operators to work on vectors of data. The type system is extended to handle pixels and dimensional analysis. Code generation is via the ILCG system that allows retargeting to multiple different SIMD instruction sets based on formal descrition of the instruction set semantics.

1  Introduction

The introduction of SIMD instruction sets[13][1][25][14] to Personal Computers potentially provides substantial performance increases, but the ability of most programmers to harness this performance is held back by two factors. The first is the limited availability of compilers that make effective use of these instruction sets in a machine independent manner. This remains the case despite the research efforts to develop compilers for multi-media instruction sets[7][23][21][28]. The second is the fact that most popular programming languages were designed on the word at a time model of the classic von Neuman computer rather than the SIMD model.

Vector Pascal aims to provide an efficient and elegant notation for programmers using Multi-Media enhanced CPUs. In doing so it borrows concepts for expressing data parallelism that have a long history, dating back to Iverson's work on APL in the early '60s[16]. We are using the word elegant in the technical sense introduced by Chaiten[6]. By an elegant algorithm we mean one which is expressed as concisely as possible. Elegance is a goal that one approaches asymtotically, approaching but never attaining. APL and J[19] allow the construction of very elegant programs, but at a cost. An inevitable consequence of elegance is the loss of redundancy. APL programs are as concise, or even more concise than conventional mathematical notation[17] and use a special characterset. This makes them hard for the uninitiated to understand. J attempts to remedy this by restricting itself to the ASCII characterset, but still looks dauntingly unfamiliar to programmers brought up on more conventional languages. The aim of Vector Pascal is to provide the conceptual gains of Iverson's notation within a framework familiar to imperative programmers.

Pascal[20]was chosen as a base language over the alternatives of C and Java. C was rejected because notations like for and declared as arithmetic operations are already overloaded for address operations in a way which precludes their use in map operations.

2  Array mechanisms for data parallelism

Vector Pascal extends the array type mechanism of Pascal to provide better support for data parallel programming in general, and SIMD image processing in particular. Data parallel programming can be built up from certain underlying abstractions[9]:

operations on whole arrays

array slicing

conditional operations

reduction operations

data reorganisation

We will first consider these in general before moving on to look at their support in other languages, in particular J, Fortran 90[9] and Nesl[3] then finally looking at how they are supported in Vector Pascal.

2.1  Operations on whole arrays

The basic conceptual mechanism is the map, which takes an operator and and a source array ( or pair of arrays ) and produces a result array by mapping the source(s) under the operator. Let us denote the type of an arry of T as T[] . Then if we have a binary operator w:(TÄT)® T , we automatically have an operator w:(T[]ÄT[])® T[] . Thus if x,y are arrays of integers k = x+y is the array of integers where ki = xi+yi :

=

+

Similarly if we have a unary operator m:( T®T) then we automatically have an operator m:(T[]®T[]). Thus z = sqr(x) is the array where zi = xi2:

= sqr(

)

The map replaces the serialisation or for loop abstraction of classical imperative languages. The map concept is simple, and maps over lists are widely used in functional programming. For array based languages there are complications to do with the semantics of operations between arrays of different lengths and different dimensions, but Iverson[16] provided a consistent treatment of these. Recent languages built round this model are J, an interpretive language[18][4][19], High Performance Fortran[9], F[24] a modern Fortran subset, Nesl an applicative data parallel language. In principle though any language with array types can be extended in a similar way. The map approach to data parallelism is machine independent. Depending on the target machine, a compiler can output sequential, SIMD, or MIMD code to handle it.

Recent implementations of Fortran, such as Fortran 90, F, and High Performance Fortran provide direct support for whole array operations. Given that are arrays with the same rank and same extents, the statements:

 REAL,DIMENSION(64)::A,BA=3.0B=B+SQRT(A)*0.5; 

would be legal, and would operate in a pointwise fashion on the whole arrays. Intrinsic functions such as SQRT are defined to operate either on scalars or arrays, but intrinsic functions are part of the language rather than part of a subroutine library. User defined functions over scalara do not automatically extend to array arguments.

J1 similarly allows direct implementation of array operations, though here the array dimensions are deduced at run time:

  a=. 1 2 3 5a1 2 3 5b=. 1 2 4 8a+b2 4 7 13 

The pair is the assignment operator in J. Unlike Fortran, J automatically overloads user defined funtions over arrays. In what follows is an expression binding the dyadic power function to the contant 2, a user defined monadic operator.

  sqr=.^&2b=.1 2 4 8b+(sqr a)*0.51.5 4 8.5 20.5 

Nesl provides similar generality; the first J example above could be expressed as:

 {a+b: a in [1,2,3,5]; b in [1,2,4,8]};=> [2, 4, 7, 13] : [int] 

and the second example as:

 {b+ sqr(a)*0.5: a in [1,2,3,5]; b in [1,2,4,8]};=> [1.5, 4, 8.5, 20.5] : [float] 

Again user defined functions can be applied element wise, to arrays ( or sequences as they are called in the language). The expressions in { } brackets termed the Apply-to-Each construct, are descended from the ZF notations used in SETL[27] and MIRANDA[30].

2.2   Array slicing

It is advantageous to be able to specify sections of arrays as values in expression. The sections may be rows or columns in a matrix, a rectangular sub-range of the elements of an array, as shown in figure 1. In image processing such rectangular sub regions of pixel arrays are called regions of interest. It may also be desirable to provide matrix diagonals[31].

 

1

1

1

1

1

2

4

8

1

2

4

16

1

2

8

512

 

 

 

 

  

 

1

1

1

1

1

2

4

8

1

2

4

16

1

2

8

512

 

 

 

 

  

 

1

1

1

1

1

2 4

8

Pascal - Arrays


Previous Page

Next Page  


Pascal programming language provides a data structure called the array, which can store a fixed-size sequential collection of elements of the same type. An array is used to store a collection of data, but it is often more useful to think of an array as a collection of variables of the same type.

Instead of declaring individual variables, such as number1, number2, ..., and number100, you declare one array variable such as numbers and use numbers[1], numbers[2], and ..., numbers[100] to represent individual variables. A specific element in an array is accessed by an index.

All arrays consist of contiguous memory locations. The lowest address corresponds to the first element and the highest address to the last element.

Please note that if you want a C style array starting from index 0, you just need to start the index from 0, instead of 1.

Declaring Arrays

To declare an array in Pascal, a programmer may either declare the type and then create variables of that array or directly declare the array variable.

The general form of type declaration of one-dimensional array is −

type array-identifier = array[index-type] of element-type;

Where,

  • array-identifier − indicates the name of the array type.

  • index-type − specifies the subscript of the array; it can be any scalar data type except real

  • element-type − specifies the types of values that are going to be stored

For example,

type vector = array [ 1..25] of real; var velocity: vector;

Now, velocity is a variable array of vector type, which is sufficient to hold up to 25 real numbers.

To start the array from 0 index, the declaration would be −

type vector = array [ 0..24] of real; var velocity: vector;

Types of Array Subscript

In Pascal, an array subscript could be of any scalar type like, integer, Boolean, enumerated or subrange, except real. Array subscripts could have negative values too.

For example,

type temperature = array [-10 .. 50] of real; var day_temp, night_temp: temperature;

Let us take up another example where the subscript is of character type −

type ch_array = array[char] of 1..26; var alphabet: ch_array;

Subscript could be of enumerated type −

type color = ( red, black, blue, silver, beige); car_color = array of [color] of boolean; var car_body: car_color;

Initializing Arrays

In Pascal, arrays are initialized through assignment, either by specifying a particular subscript or using a for-do loop.

For example −

type ch_array = array[char] of 1..26; var alphabet: ch_array; c: char; begin ... for c:= 'A' to 'Z' do alphabet[c] := ord[m]; (* the ord() function returns the ordinal values *)

Accessing Array Elements

An element is accessed by indexing the array name. This is done by placing the index of the element within square brackets after the name of the array. For example −

a: integer; a: = alphabet['A'];

The above statement will take the first element from the array named alphabet and assign the value to the variable a.

Following is an example, which will use all the above-mentioned three concepts viz. declaration, assignment and accessing arrays −

program exArrays; var n: array [1..10] of integer; (* n is an array of 10 integers *) i, j: integer; begin (* initialize elements of array n to 0 *) for i := 1 to 10 do n[ i ] := i + 100; (* set element at location i to i + 100 *) (* output each array element's value *) for j:= 1 to 10 do writeln('Element[', j, '] = ', n[j] ); end.

When the above code is compiled and executed, it produces the following result −

Element[1] = 101 Element[2] = 102 Element[3] = 103 Element[4] = 104 Element[5] = 105 Element[6] = 106 Element[7] = 107 Element[8] = 108 Element[9] = 109 Element[10] = 110

Pascal Arrays in Detail

Arrays are important to Pascal and should need lots of more details. There are following few important concepts related to array which should be clear to a Pascal programmer −

ConceptDescription

Multi-dimensional arrays

Pascal supports multidimensional arrays. The simplest form of the multidimensional array is the two-dimensional array.

Dynamic array

In this type of arrays, the initial length is zero. The actual length of the array must be set with the standard SetLength function.

Packed array

These arrays are bit-packed, i.e., each character or truth values are stored in consecutive bytes instead of using one storage unit, usually a word (4 bytes or more).

Passing arrays to subprograms

You can pass to a subprogram a pointer to an array by specifying the array's name without an index.

Previous Page

Print

PDF

Next Page  


0 comments

Leave a Reply

Your email address will not be published. Required fields are marked *