7 Arrays and Vectors

So far we have met just 26 variables, called A to Z. Suppose you wanted to plot a graph showing the mean temperature for every month of the year. You could, at a pinch, use the twelve letters A to L to represent the mean temperatures, and read in the temperatures by saying:

      INPUT A,B,C,D,E,F,G,H,I,J,K,L

However there is a much better way. A mathematician might call the list of temperatures by the names:

t1, t2, t3, ..... t12.

where the 'subscript', the number written below the- line, is the number of the month in the year. This representation of the twelve temperatures is much more meaningful than using twelve different letters to stand for them, and there is no doubt about which symbol represents the temperature of, for example, the third month.

A similar series of variables can be created in ATOM BASIC, and these are called 'arrays'. Each array consists of an array 'identifier', or name, corresponding to the name 't' in the above example, and a 'subscript'. On most computers there is no facility for writing subscripts, so some other representation is used. Each member of the array can act as a completely independent variable, capable of holding a value just like the variables A to Z. The members of an array are called the array 'elements'. The total number of possible elements depends on how the array was set up; in the above example there were twelve elements, with subscripts from 1 to 12.

In addition to the standard type of array, ATOM BASIC provides two other types of array called 'byte vectors' and 'word vectors'. Byte vectors are useful when only a small range of numbers are needed, and they use less storage space than word arrays. Word vectors use the same amount of storage as arrays, but can be manipulated in a more
flexible manner.

7.1 Arrays - AA to ZZ

The array in ATOM BASIC consists of a pair of identical letters a followed by the subscript in brackets: for example, EE(3). Each element in this type of array can contain numbers as large as the simple variables A to Z, namely, between about -2000 million and 2000 million.

Before an array can be used space must be reserved for it by a DIM, or 'dimension', statement which tells BASIC how large the array - is to be. For example, to reserve space for an array called AA with the five elements AA(0), AA(1), AA(2), AA(3), and AA(4), the statement would be:

      DIM AA(4)

The DIM statement allocates space for arrays starting at the first free memory location after the program text. If this were the first a DIM statement encountered in the program the element AA(0) would be at TOP, above the program text:

TOP:
? ? ? ?
^
AA(0)
^
AA(1)
^
AA(2)
^
AA(3)

The question marks represent unspecified values, depending on what the array contained when it was dimensioned. If now another array were dimensioned with the statement:

      DIM BB(3)

space for the array BB would be reserved immediately following on from AA.

Array elements can appear in expressions, and be assigned to, just like the simple variables A to Z. For example, to make the value of AA(3) become 776 we would execute:

      AA(3)=776

Then we could execute:

      AA(1)=AA(3)*2 
      AA(0)=AA(3)-6

and so on. The resulting array would now be:

TOP:
770 1552 ? 776 ?
^
AA(0)
^
AA(1)
^
AA(2)
^
AA(3)
^
AA(4)

There are two places in BASIC programs where array elements may not be used; these are:

1. As the control variable in a FOR...NEXT loop.

2. In an INPUT statement.

In these two cases the simple variables, A to Z, must be used.

7.1.1 Histogram

The following program illustrates the use of arrays to plot a histogram of the temperature over the twelve months of the year. The temperatures, assumed to be in the range 0 to 100, are first entered in and are stored in the array TT(1..12).

    1 REM Histogram
   10 DIM TT(12)
   20 FOR J=1 TO 12;INPUT K
   30 TT(J)=K; NEXT J
   40 PRINT $12; CLEAR 0; @=5
   50 MOVE 60,12; DRAW 12,12
   60 DRAW 12,42
   70 FOR N=11 TO 0 STEP -1
   80 IF N=7 PRINT "TEMP."
   90 IF N%2=0 PRINT N*10
  100 PRINT';NEXT N
  110 PRINT "      JAN MAR MAY JUL SEP NOV"'
  120 PRINT "        FEB APR JUN AUG OCT DEC"'
  130 PRINT "                MONTH"'
  140 FOR N=1 TO 12; J=11+4*N
  150 MOVE J,12; DRAW J,(TT(N)*3/10+12) 
  160 NEXT N; END
Description of Program:
20-30     Input 12 values
40        Clear screen
50-60     Draw axes
70-100    Label vertical axis
110-130   Label horizontal axis
140-160   Plot histogram bars
Program size: 415 bytes 
Array storage: 52 bytes

7.1.2 Sorting Program

The following program illustrates the use of arrays to sort a series of numbers into ascending order. It uses a fairly efficient sorting procedure known as the 'Shell' sort. The program, as written, reads in 20 numbers, calls a subroutine to sort the numbers into order, and prints the sorted numbers out.

    1 REM Sorting
    5 DIM AA(20)
   10 FOR N=1 TO 20; INPUT J
   20 AA(N)=J; NEXT N
   30 N=20; GOSUB s
   40 FOR N=l TO 20; PRINT AA(N)' 
   50 NEXT N
   60 END
  100sM=N
  110 DO M=(M+2)/3
  120   FOR I=M+1 TO N
  130     FOR J=I TO M+1 STEP -M
  140       IF AA(J)>=AA(J-M) GOTO b
  150       T=AA(J); AA(J)=AA(J-M); AA(J-M)=T
  160     NEXT J
  170b  NEXT I
  180 UNTIL M=l; RETURN
Description of Program:
5-20      Read in array of numbers
30        Call Shell sort
40-50     Print out sorted array
100-180   s: Shell sort subroutine
140-150   Swap elements which are out of order.
Variables:
AA(1..20) - Array to hold numbers
I,J - Loop counters
N - Number of elements in array AA 
M - Subset step size
T - Temporary variable
Program size: 332 bytes
Array storage: 84 bytes

7.1.3 Arbitrary-Precision Arithmetic

The following program allows powers of two to be calculated to any precision, given enough memory. As it stands the program will calculate all the powers of 2 having less than 32 digits. The digits are stored in an array AA, one digit per array element. Every power of 2 is obtained from the previous one by multiplying every element in the array by 2, and propagating a carry when any element becomes more than one digit.

    5 REM Powers of Two
   10 DIM AA(31)
   20 @=1; P=0
   30 AA(0)=1
   40 FOR J=1 TO 31
   50   AA(J)=0
   60 NEXT J
   70 DO J=31
   80   DO J=J-1; UNTIL AA(J)<>0
   85   PRINT'"2^" P "="
   90   FOR K=J TO 0 STEP -1
   94     PRINT AA(K)
   96 NEXT K
  110   C=0
  120   FOR J=0 TO 31
  130     A=AA(J)*2+C
  140     C=A/10
  150     AA(J)=A%10
  160   NEXT J
  170   P=P+1
  180 UNTIL AA(31)<>0
  190 END
Description of Program:
40-60     Zero array of digits
80        Ignore leading zeros
85-96     Print power
110-160   Multiply current number by 2
180       Stop when array overflows.
Variables:
AA - Array of digits; one digit per element
C - Decimal carry from one digit to next
J - Digit counter
K - Digit counter
P - Power being evaluated
Program size: 356 bytes
Array usage: 124 bytes
Total memory: 480 bytes.

7.1.4 Digital Waveform Processing

The following program uses a 256-element array to store a waveform which can be low-pass filtered, converted to a square wave, or printed out.

     1 REM Digital Waveform Processing
    5 DIM AA(255)
   10 H=2000
   15 CLEAR4
   23 GOS.s; GOS.q
   25 Z=160; GOS.p
   28 GOS.l
   30 Z=96; GOS.p
   32 GOS.s
   34 Z=32; GOS.p
   90 END
 1000pREM Plot Waveform
 1005 MOVE 0,96
 1010 FOR N=0 TO 255
 1020 PLOT13,N,(Z+AA(N)/H)
 1030 NEXT N
 1040 RETURN
 2000sREM Make Sine Wave
 2010 S=0;C=40000
 2020 FOR N=0 TO 255
 2030 AA(N)=-S
 2040 C=C-S/10
 2050 S=S+C/10
 2060 NEXT N
 2070 RETURN
 3000qREM Make Square Wave
 3010 FOR N=0 TO 255
 3020 IF AA(N)>=0 AA(N)=40000
 3030 IF AA(N)<0 AA(N)=-40000
 3035 NEXT N
 3040 RETURN
 4000lREM Low Pass Filter
 4010 B=0
 4020 FOR N=0 TO 255
 4030 B=AA(N)*360/1000+B*697/1000
 4040 AA(N)=B; NEXT N
 4050 RETURN
Description of Program:
23        Calculate a square wave
25        Plot it at top of screen
28        Low-pass filter the square wave
30        Plot it in centre of screen
32        Calculate a sine wave
34        Plot it at bottom of screen
1000-1040 p: Plots waveform
2000-2070 s: Calculates a sine wave. 
3000-3040 q: Squares-up the waveform 
4000-4050 l: Low-pass filters the waveform
Variables:
AA(0...255) - Array of points, values between -40000 and 40000.
B - Previous value for low-pass filter
C - Cosine of waveform
H - Scalinq factor for plotting waveforms
N - Counter
S - Sine of waveform
Z - Vertical coordinate for centre of waveform.
Program size: 564 bytes.
Array storage: 1024 bytes
Total memory: 1588 bytes
Sample plot:

7.1.5 Subscript Checking

Many BASIC interpreters perform extensive checking whenever an array element is used in a program. For example, if an array were dimensioned:

      DIM RR(10)

then every time the array were used the subscript would be checked to make sure that it was both 0 or greater, and 10 or less. Obviously these two checks slow down the execution of a program, and so in ATOM BASIC only the first check is performed, so that only positive subscripts are allowed. It is left to the programmer to ensure that subscripts do not go out of range. Assigning to an array whose subscript is out of range will change the values of other arrays, or strings, dimensioned after that array.

If required, the programmer can easily add array subscript checking; for example, if the array assignment were:

      RR(A)=35
the statement:
      IF A>10 THEN ERROR

could be added before the assignment to cause an error if the array subscript, A, went out of range.

7.1.6 Multi-Dimensional Arrays

The standard types of array in ATOM BASIC are one-dimensional. In other words, they have just one subscript, and so can be visualised as lying in a straight line; hence the name 'array'.

Sometimes it is convenient to make each element of an array represent a cell in a square 'matrix'; each element would then have two subscripts corresponding to the column and row of that square.
Such two-dimensional arrays are called 'matrices'. Consider the following representation of a 3 by 6 matrix:

  0 1 2 3 4 5
0            
1            
2         x  

The whole matrix has 3 x 6 = 18 elements, and the element shown with an X would have the subscripts (2,4).

ATOM BASIC does not have a direct representation for two-dimensional (or higher dimension) arrays, but they are easily represented using the single-dimension arrays AA to ZZ as described in the following sections.

7.1.7 Calculation of Subscripts

To represent a two-dimensional matrix using a one-dimensional array imagine the matrix divided into rows as shown:

  0 1 2 3 4 5
0            
  0 1 2 3 4 5
1            
  0 1 2 3 4 5
2            

The first element of row 1, with subscripts (1,0), follows immediately after the last element of row 0, with coordinates (0,5). Consider the general case where the matrix has M rows numbered 0 to N-l, and N columns numbered 0 to N-1. The matrix can be dimensioned, using a one-dimensional array, with the DIM statement:

      DIM XX(M*N-1)

Any array element, with subscripts A and B, can be referenced as:

      XX(A*N+B)

In the earlier example the array had dimensions 3 x 6 and so would be dimensioned:

      DIM XX(17)

The array element with subscripts (2,4) would be given by: xx(16)

7.1.8 Solving Simultaneous Equations

The following program will solve a number of linear simultaneous equations, using a matrix to hold the coefficients of the equations, and a matrix inversion technique to find the solution. The program prints the solutions as integers, where possible, or as exact fractions.

This method has the advantage over the standard pivotal condensation technique that for integer coefficients the answers are exact integers or fractions.

The example run shown solves the pair of equations:

 a + 2b + 1 = 0
4a + 5b + 2 = 0
   10 REM Simultaneous Equations 
   50 INPUT"NUMBER OF EQUATIONS="N 
   60 I=N*N;J=N*(N+1)
   65 DIM AA(I),CC(J),II(N)
   70 @=0;FOR I=1TON;FOR J=1TO N+1
   80 PRINT"C("I","J")=";INPUT C
   90 CC((I-1)*(N+1)+J)=C;NEXT J;NEXT I
  100 L=N+1;GOSUB c;E=D;M=l-2*(N%2)
  110 PRINT'"SOLUTION:"'
  112 IF E<0 E=-E;M=-M
  115 IF E=0;PRINT"DEGENERATE!"';END
  120 FOR L=1TON;GOSUB c
  125 PRINT"X("L")=  "
  130 A=M*D;B=E;DO A=A%B
  140 IF ABS(B)>ABS(A) THEN T=B;B=A;A=T
  150 UNTIL B=0;A=ABS(A)
  151 P.(M*D)/A;IF E/A<>1 PRINT"/"E/A
  155 M=-M;PRINT';NEXT L;END
  160cFOR I=1T0N;FOR J=1TON;K=I*N-N+J
  170 IF J<L AA(K)=CC(K+I-1)
  180 IF J>=L AA(K)=CC(K+I)
  190 NEXT J;NEXT I
  200dD=0;F=l;S=l
  210 FOR J=1TON;II(J)=J;F=F*J;NEXT J
  215 GOSUB f
  220 FOR H=2TOF;GOSUB e;NEXT H;RETURN
  230eI=N-1;J=N
  240gIF II(I)>=II(I+1) I=I-1;GOTO g
  250hIF II(I)>=II(J) J=J-1;GOTO h
  260 GOSUB i;I=I+1;J=N;IF I=J GOTO f
  270 DO GOSUB i;I=I+1;J=J-1;UNTIL I>=J
  280fP=I;FOR K=1TON;P=P*AA(N*K-N+II(K))
  290 NEXT K;D=D+S*P;RETURN
  300iK=II(I);II(I)=II(J);II(J)=K
  310 S=-S;RETURN
Description of Program:
50-60     Allocate space for matrix
70-90     Read in matrix of coefficients
120-155   Print solutions
130-150   Find GCD of solution, so it is printed in lowest terms
160-190   c: Permute terms to obtain next addition to determinant; i.e. 
          for 5 equations, starting with (1,2,3,4,5) run through all 
          permutations to (5,4,3,2,1).
280-290   f: Add in next product to determinant.
300-310   i: Swap terms in permutation.
Variables:
AA(1...N*N) - Matrix
CC(1...N*N+N) - Matrix of coefficients
S - Signature of permutation.
Program Size: 932 bytes.
Variable Space: (2*(N*N+N)+3)*4 bytes
Sample run:
>RUN
NUMBER OF EQUATIONS=?2
C(1,1)=?1
C(1,2)=?2
C(1,3)=?1
C(2,1)=?4
C(2,2)=?5
C(2,3)=?2
SOLUTION: 
X(1)=  1/3 
X(2)=  -2/3

7.2 Byte Vectors Using, '?'

It is sometimes wasteful of memory to allocate space for numbers over the range provided by word arrays so a second type of array representation is provided which only allocates one byte, rather than four bytes, for each array element. These are referred to as 'byte vectors', and they are in effect one-dimensional arrays. Byte vectors differ from word arrays in that they use one of the simple variables A to Z to hold the 'base' address of the array; i.e. the address in memory where the zeroth element of the array will reside. The array subscripts are simply 'offsets' from this base address; i.e. the subscript is added to the base address to give the address of the array element. The vector elements are written as:

 A?0, A?1, A?2, ... etc

where A is the simple variable used to hold the base address of the vector, and the number following the question mark is the subscript.

Note that the zeroth element of a byte vector, A?0, is equivalent to ?A, the contents of the location with address A. Similarly A?1 is equivalent to ?(A+1), and so on.

Byte vectors can be dimensioned by the DIM statement; for example, to dimension a byte vector with elements from A?0 to A?11 the statement would be:

      DIM A(11)

Because the DIM statement dimensions arrays and vectors from the end of the program onwards, the above DIM statement is equivalent to:

      T=TOP; A=T; T=T+12

where T is a variable used to keep track location. Note that space for vectors can be reserved anywhere in memory, as distinct from arrays which can only be assigned from TOP onwards using the DIM statement. For example, to assign space for a vector S corresponding to the screen memory, simply execute:

      S=#8000

Elements of this vector would then correspond to locations on the screen; e.g. S?31 is the location corresponding to the top right-hand corner of the screen.

Each element of a byte array can hold a positive number between 0 and 255, or a single character. Strings are simply byte vectors containing characters. Note that the subscript of a byte array can be an arbitrary expression provided that it is enclosed in brackets.

7.3 Word Vectors Using '!'

A second representation for word arrays is provided in ATOM BASIC using the word indirection operator '!', and is mentioned here for completeness, although for simple problems involving arrays the word arrays AA to ZZ are probably more convenient. Word vectors are similar to the byte vectors already described, but each element of the vector consists of a word rather than a byte. Each element consists of the base address variable separated from the subscript, or offset, by a 'pling' '!'. Note that the subscript should be incremented by 4 for each element, since each element is offset 4 bytes from the previous one. For example, a word vector W might have the six elements:

W!0, W!4, W!8, W!12, W!l6, W!20.

Space can be dimensioned for word vectors by using the DIM statement, and allowing 4 bytes per element; for example, to provide storage for the above 6 elements, execute:

      DIM W(23)

Note that the zeroth element of the vector, W!0, is equivalent to !W.

7.3.1 Prime Numbers

The following program finds all the prime numbers up to 99999. It uses a word vector to store primes already found, and only tests new candidates for divisibility by these numbers:

    1 REM Prime Numbers
   10 @=8;S=4;Z=0;J=TOP;G=J;!G=3;PW+S
   20 FORT=3TO99999STEP2
   30cIFT%!G=Z G=J;N.
   40 IFT>!G*!G G=G+S;G.c
   50 P.T;!P=T;G=J;P=P+S;N.
   60 END
Description of Program:
10        Set up vector
20        Test all odd numbers
30        If divisible, try another.
40        Have we tried enough divisors?
50        Must be prime - print it.
Variables:
!G - Divisor being tested
J - Equal to TOP
!P - Vector of divisors
S - Bytes per word
T - Candidate for prime
Z - Constant zero.
Program size: 155 bytes 
Vector: as required.

7.3.2 Call by Reference

A major advantage of word vectors over the word arrays is that their base addresses are available as values, and so can be passed to subroutines. As an example, consider this program:

   10 A=TOP; B=A+40
   .
   .
   90 P=A; GOSUB p; REM Output A
   94 P=B; GOSUB p; REM Output B
   98 END
   100pREM Print 10 Elements of array P
   105 @=8; PRINT '
   110 FOR J=0 TO 39 STEP 4
   120   PRINT P!J
   130 NEXT J
   140 PRINT '
   150 RETURN

In this example subroutine p can be used to print any array by passing its base address over in the variable P; this is known as a 'call by reference' because the subroutine is given a reference to the array, rather than the actual values in the array.

7.3.3 Arbitrary Precision Powers

The following program illustrates the use of word vectors to calculate the value of any number raised to any other number exactly, limited only by the amount of memory available. The program stores four decimal digits per word, so that the product of two words will not cause overflow, and the result is calculated as a word vector.

    1 REM Arbitrary Precision Powers
    5 T=#3BFF
   10 H=(T-TOP)/3; DIM P(H),S(H),D(H)
   15 H=10000
   20 @=0;PRINT'"     POWER PROGRAM"
   30 PRINT'"  COMPUTES Y X, WHERE x>0 AND Y>0"
   40 INPUT'"  VALUE OF Y"Y,"  VALUE OF X"X
   50 IFX<1ORY<1PRINT"  VALUE OUT OF RANGE";RUN
   60 N=Y;N=X;GOSUBp
   70 PRINT Y" "X"="P!!P;IF!P<8 RUN
   90 F.L=!P-4T04STEP-4
   95 IFL!P<1000P.0
  100 IFL!P<100P.0
  110 IFL!P<10P.0
  120 P.L!P;N.;RUN
  140*
  200pJ=M;IFN%2=0J=1
  210 R=P;GOS.e;J=M;R=S;GOS.e;IFN=1R.
  250 B=S;DOA=B;GOS.m;B=E
  255 N=N/2;A=P;IFN%2GOS.m;P=E
  260 U.N<2;R.
  280*
  300m!D=!A+!B+4;F.J=4TO!D+4S.4
  310 D!J=0;N.;W=D-4
  320 F.J=4TO!B S.4;C=0;G=B!J
  325 V=W+J;F.L=4TO!A S.4
  330 Q=A!L*G+C+V!L;V!L=Q%H
  340 C=Q/H;N.;V!L=C;N.
  370 DO!D=!D-4;U.D!!D<>0;E=D;D=A;R.
  380*
  400e!R=0;DO!R=!R+4;R!!R=J%H
  410 J=J/H;U.J<1;R.
Description of Program:
5         Set T to top of lower text space.
10        Divide available memory between P, S, and D
20-40     Read in values of Y and X 
50        Disallow negative values
60        Calculate power
70        Print result if fits in one word
90        Print rest of result, filling in leadinq zeros.
140       Blank line to make listing clearer.
200-260   p: Calculates power. Looks at binary representation of X and 
          for each bit squares B, and if bit is a 1 multiplies P by 
          current B.
300-370   m: Multiply together the vectors pointed to by A and B and 
          put the result into the vector pointed to by D. Pointers to 
          vectors get changed; E points to result.
400-410    e: Unpack J into vector pointed to by R; store number of 
           words in !R.
Variables:
D!0... - Workspace vector
H - Radix for arithmetic
P!1... - Vector for unpacked result
!P - Number of elements used in P
S!0... - Workspace vector
T - Top of available memory
Program size: 733 bytes.
Additional storage: as available.
Sample run: 
>RUN
        POWER PROGRAM
     COMPUTES Y^X, WHERE X>0 AND Y>0
     VALUE OF Y?16
     VALUE OF X?64
   16^64=115792089237316195423570985008687907853269984665640564039457584007913129639936

7.3.4 Vectors of Vectors

A second way of representing two-dimensional arrays is possible using the ATOM's indirection operators '?' and '!'; this avoids the need for a multiplication to calculate the subscript, but does require slightly more storage. The idea is to think of a two-dimensional matrix as a vector of vectors; first a vector is created containing the addresses of the rows of the matrix. For example, for a matrix called X with columns 0 to M, and rows 0 to N, the following statements will set up the vector of row addresses:

      DIM X(2*N-1)
      FOR J=0 TO N*2 STEP 2; DIM Q(M); X!J=Q; NEXT J

A word array is used to hold the base addresses. Q is a variable used to hold the base address temporarily. Now that the vector of row base addresses has been set up, the element with subscripts A,B is:

      X!(A*2)?B

Next chapter