ar for instance by ar(5).
You can view successive array elements as lying in sequence in the memory
of the computer, and that is in fact a correct view.
REAL ar(20)or declaring type and size separately, eg
DIMENSION ar(20)
REAL ar
where the type declaration can stay implicit.
The size of an array is statically determined: you cannot read it in and
then create the array; you have to declare it `large enough' in the source.
The array bound can be an expression, but it can involve only constants
or named constants.
The first element of the array is ar(1); if your problem is
more naturally expressed with a lower bound other than one, you can declare
the array as
DIMENSION ar(lo:hi)where
lo and hi are integers.
x(i) = 5.1
k = 2*iarr(5)-iarr(ip(3))
In the second line an integer array ip was used to provide
the subscript in the array iarr.
The subscript expressions used have to have a value between the upper and lower bound of the array. However, the compiler cannot determine whether this will be the case, since subscript expressions can be computed during the run of the program.
It is then your responsibility to ensure that you will not take elements
outside the bounds of the array. Doing so will give undefined results, or
may crash your program. Often, compilers have an option to let bounds be
tested during runtime. Since this slows down your program considerably,
it is something you typically do during the testing phase of the program.
DO loops DO 10 i=1,n
PRINT *,a(i)
10 CONTINUE
but this leads to n lines each with one number on them. To
write the array values on a single line, one needs the `implied DO
loop' construct:
PRINT *,(a(i),i=1,n)This can also be used for input of array elements.
Implied do loops can also be used in array initialisation.
F90: slices.
SUBROUTINE s(x)the routine can be called with an array element as argument:
DIMENSION ar(10)
...
CALL s(ar(5))
and the routine can use its argument the same way as when a variable had
been passed.
If the subprogram assigns a value to its scalar argument, and the actual argument is an arrary element:
SUBROUTINE s(x)
x = 2.
RETURN
END
DIMENSION ar(10)
...
CALL s(ar(5))
then the effect in the calling program unit would be the same as
ar(5) = 2.
SUBROUTINE s(x)
DIMENSION x(7)
If the array size is declared explicitly in the subprogram, it is the responsibility
of the programmer to make sure that a sufficiently large array is passed
to the subprogram:
DIMENSION ar(8)
...
CALL s(ar)
Instead of calling the subprogram with the array name, one could supply
another element:
CALL s(ar(2))In this example that corresponds to supplying the segment with the seven elements
ar(2)..ar(8) to the subprogram. This also shows that
you can tinker with the bounds of an array when passing it: the subroutine
could equally validly have been written as SUBROUTINE s(x)
DIMENSION x(-3:3)
CALL s(ar,8)
...
SUBROUTINE s(x,n)
DIMENSION x(n)
Since the size of this array can be different each time the subroutine is
called, this is called an `adjustable array'. Instead of passing the size
as argument, it can also be kept in a COMMON
block.
It is even allowed not to declare the size of the array at all in the subprogram, but merely to declare that it is an array:
SUBROUTINE s(x)
DIMENSION x(*)
Assumed size, size passed, adjustable array, assignment to
SUBROUTINE copy(x,y,n)
REAL x(n),y(n)
DO 10 i=1,n
y(i) = x(i)
10 CONTINUE
RETURN
END
and consider the difference between the following calls:
DIMENSION z(11)
CALL copy(z(2),z(1),10)
or
CALL copy(z(1),z(2),10)The first call will have the intended effect of moving a block of data, but the second one has the effect of setting all array elements equal to the first.
DATA statement
can be used in various ways to initialise an array. To initialise an array,
you can either write out values
DIMENSION X(5)
DATA X/1.1,2.2,3.3,4.4,5.5/
or use repeated values
DATA X/5*1.2/if all elements are to receive the same value. Parts of an array can be initialised by using implied
DO
loops:
DATA x(1),(x(i),i=2,5)/1.,4*2./
DIMENSION a(10,20)then a 10 by 20 matrix can be stored in
a. You refer to elements
in a multi-dimensional array by supplying enough subscripts:
a(5,12) = 17.2For any or all of the dimensions upper and lower bounds can be specified separately:
DIMENSION a(18,-1:1,0:15)
That is, if a matrix is declared as
INTEGER mat(2,2)then its elements are, in sequence:
mat(1,1), mat(2,1), mat(1,2), mat(2,2)This is often described as "the leftmost index varies fastest".
This storage scheme allows you to play tricks with reshaping
arrays by passing them as routine arguments. There are also practical implications
when traversing the array. By letting an index run over the second and higher
dimensions, the number of cache misses, memory bank conflicts, page faults,
can greatly increase.
DIMENSION ar(3,4,5)
...
DO 10 i=1,5
CALL subr(ar(1,1,i))
...
SUBROUTINE subr(x)
DIMENSION x(3,4)
There are more tricks with array dimensions. For instance, with the subroutine
as above, the same main program could have been written as DIMENSION ar(12,5)
...
DO 10 i=1,5
CALL subr(ar(1,i))
or even DIMENSION ar(60)
...
DO 10 i=1,5
CALL subr(ar(1+(i-1)*12))
The `star notation' for arrays passed as arguments
can be used for higher dimensional arrays, but only for the right-most dimension.
Eg, the above subroutine could have been written: SUBROUTINE subr(x)
DIMENSION x(3,4,*)
Multidimensional bound checking
Exercise: simulate multi-dim in one dimensional,
avoid recomputing index