! 15. Arrays.						File: array15.f90
!------------------------------------------------------------------------------!

MODULE binomial
	IMPLICIT NONE
CONTAINS
	SUBROUTINE coefficient(nmax,c)
		IMPLICIT NONE

		! This example evaluates the binomial coefficients c(n,m) and 
		! stores the values in the matrix (array) c(n,m)		    		
		! declarations
		INTEGER :: n,m
		INTEGER, INTENT(IN) :: nmax
		! specify the dimensions of the two dimensional array 
		! (matrix) c(n,m).
		INTEGER, DIMENSION(0:nmax,0:nmax), INTENT(OUT) :: c

		! initialize array. Note how all elements are set to zero 
		! by this one statement. Fortran90 has the facility to treat 
		! arrays as single objects. 
		c = 0

		! use recurrence relation c(n,m)=c(n-1,m-1) + c(n-1,m) 
		! where m<n to generate elements

		c(0,0) = 1
		c(1,0) = 1
		c(1,1) = 1

		DO  n = 2,nmax
	   		c(n,0) = 1
	  		c(n,n) = 1

	   		DO  m = 1,n-1
	      			c(n,m) = c(n-1,m-1) + c(n-1,m)
	   		END DO
		END DO
	END SUBROUTINE coefficient


	SUBROUTINE output(nmax,c)
		IMPLICIT NONE

		! declarations
		INTEGER :: n,m
		INTEGER, INTENT(IN) :: nmax
		INTEGER, DIMENSION(0:nmax,0:nmax), INTENT(IN) :: c

		! output
		! The following statement will print out the elements 
		! column by column in one long list

		PRINT *
		PRINT *, 'This program introduces Fortran90 arrays and '
		PRINT *, 'shows alternative ways in which they may be output.'
		PRINT *
		PRINT *, 'This example calculates the binomial coefficients'
		PRINT *, 'C(n,m). (In other words, Pascal''s triangle!)'

		PRINT *
		PRINT *, 'Array C(n,m) printed as a single list, column'
		PRINT *, 'by column:'
		PRINT *

		PRINT *
		PRINT *, c
		PRINT *

		! Mathematically, we wish to print out the elements row by row, 
		! one row to a line. The following "implied" DO loop does this. 
		! Look at the configuration of the output. Observe Pascal's 
		! triangle.

		PRINT *, 'Array displayed in matrix format: '
		PRINT *

		DO  n = 0,nmax
	  		PRINT *, (c(n,m), m=0,nmax)
		END DO

		! this method is a waste of storage since the upper triangle of 
		! elements are never needed (m<=n by definition). Likewise 
		! there is symmetry in the binomial coefficients themselves: 
		! 		C(n,m) =  C(n,n-m). 
		! Scope for considerable improvements in this algorithm!

	END SUBROUTINE output

END MODULE binomial


PROGRAM array
	USE binomial
	IMPLICIT NONE

	! declarations
	INTEGER, PARAMETER :: nmax=6

	INTEGER, DIMENSION(0:nmax,0:nmax) :: c

	! calculate the matrix c
	CALL coefficient(nmax,c)

	! output matrix c
	CALL output(nmax,c)

END PROGRAM array


!! 1.	Having used vectors and matrices, we are already familiar with the 
!!	idea of an array. However, in Fortran, the concept is more general.
!!	An ARRAY is simply a means of providing a single name for a whole
!!	ordered list, or table, of data. 
!!
!!	Fortran90 provides extensive and powerful array processing features.
!!	Arrays may be treated as single objects and an extensive range of 
!!	array operations exist. This is one of the major advances in Fortran90
!!	over earlier versions and when compared to other languages.

!! 2.	The simplest type of array is an ordered list, say a list of 
!!	1000 experimental values, which you wish to record, perhaps
!!	find the mean and variance of, fit a straight line or polynomial 
!!	curve to, or whatever. Therefore a NAME has to be assigned to this
!!	array, and its individual ELEMENTS identified by a SUBSCRIPT. Since,
!!	we cannot type subscripts these are placed in brackets after the array
!!	name. Give this array the name DATA and suppose that it contains 1000 
!!	elements then its individual elements are written DATA(i) where i, the 
!!	subscript, can take any value from 1 to 1000. It will also be necessary 
!!	to declare this array so that the computer knows what type of entries 
!!	it has to store (INTEGER, REAL, etc) and how many storage cells to 
!!	reserve for this array (1000 here).
!!
!!	This can be generalised to collections of data identified by more than
!!	one subscript, as in the program above where c(n,m) has two subscripts.
!!	Fortran allows up to a maximum of SEVEN subscripts.
!!
!!	Each subscript relates to one DIMENSION of the array, the subscript 
!!	ranging between specified lower and upper bounds.
!!
!!	The number of subscripts of an array is its RANK.
!!
!!	The EXTENT of a particular dimension is the number of elements in 
!!	that dimension.
!!
!!	The SIZE of the array is the total number of elements in the array.
!!
!!	The SHAPE of an array is determined by its rank and the extent of 
!!	each dimension. The shape can be stored in a rank-1 array whose 
!!	elements are the extents of the corresponding dimension.
!!	[Note that the shape does not include details of the index bounds, 
!!	only their extents.]

!! 3.	Formally:
!!
!!	An ARRAY is a subscripted variable: a collection of storage cells all
!!	of the same type and having a single name (identifier), in which the 
!!	individual cells (ARRAY ELEMENTS) are specified by subscripting. These
!!	subscript-values must be integers and are written in parenthesis after
!!	the array identifier separated by commas.
!!
!!	An array can be of type INTEGER, REAL, COMPLEX, LOGICAL, CHARACTER .
!!
!!	Subscripts may be arithmetic expressions.
!!
!!	e.g. x(i), velocity(t,x), grade(i**2, 3*j) are valid array elements.

!! 4.	Array Declarations:
!!
!!	As with any data type, arrays must be declared in order to specify
!!	what type of elements it has AND how many there are of them. This
!!	is a straightforward extension of the declaration of simple data types
!!	with the added "dimensioning" of each subsrcipt. For example, a real 
!!	one dimensional array 'array' with elements from `array(1)' to 
!!	'array(9)' would be declared as:
!!
!!		REAL, DIMENSION(9) :: array
!!	or
!!		REAL :: array(9)
!!
!!	The former is preferred. It makes it more obvious that a variable 
!!	represents an array. 
!!
!!	If the subscripts do not start at 1, then the range has to be made 
!!	explicit. For example, if they range from 0 to 9 then we would write 
!!
!!		REAL, DIMENSION(0:9) :: array
!!
!!	Other examples:
!!
!!	   REAL, DIMENSION(0:25,0:10) :: x, y, weight(1:1000, 0:200)
!!	   INTEGER, DIMENSION(3) :: age, height(-25:25), year
!!	   CHARACTER(LEN=10), DIMENSION(0:5000, 1:200, 100:300, 25:50) :: char 
!!
!!	There is a dimension statement for each subscript which may span any
!!	range of positive and negative numbers.	
!!
!!	The above are all examples of EXPLICIT-SHAPE ARRAYs where the bounds 
!!	of each dimension are explicitly known. Other types of array will be 
!!	met later.

!! 5.	Order of storage of array elements:
!!
!!	The only time one needs to be aware of the order in which array 
!!	elements are ordered/stored is during input and output.
!!
!!	The elements of a rank-1 array (a list) are stored in the order of 
!!	their subscripts.
!!
!!	The elements of rank-2 arrays are stored column by column. Thus
!!	when storing the elements x(i,j), 'i' will run through all of its values
!!	for a given 'j' before 'j' is incremented by 1 and the process repeated.
!!
!!	For multidimensional arrays, the elements are stored such that the 
!!	first subscript varies most quickly and the last most slowly.

!! 6.	Array elements may be used in operations just like any other scalar 
!!	variable.

!! 7.	Implied DOloop.
!!
!!	Note how the matrix c(n,m) in the above program was printed out. This
!!	is an example of an implied DO loop. All the elements in a given row (n)
!!	are printed on a line (m=0,nmax). Thus the "implied" loop varies the 
!!	index m. Successive rows are printed by means of the usual DOloop.
!!	Note what would have happened if we had written
!!
!!			DO  n = 0,nmax
!!			   DO m = 0, nmax
!!	  		      PRINT *, c(n,m)
!!			   END DO
!!			END DO
!!
!!	For more on implied DOloops see the next section.

!! 8.	Exercises.
!!
!!	(a) Write a program to read in 20 real data values, find their sample
!!	mean, sample standard deviation, how many values are above the mean,
!!	and which are the maximum and minimum values.
!!	[For n data values, sample mean = sum of values/n
!!			    sample standard deviation = square root { ( sum
!!	of squares of difference of values from mean ) / (n-1) ]
!!
!!	(b) Write a program to smooth a set of data values. Suppose there are
!!	'npoints' data points whose values are f(i), i=0,npoints-1. All values
!!	(except the first and last) are to be replaced by
!!
!!		f(i) = ( f(i-1) + f(i) + f(i+1) ) / 3.0
!!
!!	(c) Write a program to multiply an n by n matrix 'arr' by an n x 1 
!!	vector 'vec1' calling the answer 'vec2' .
!!	[Fortran90 has an intrinsic function MATMUL for multiplying two 
!!	matrices. For more on this see later.]

!! 	END OF FILE: array15.f90
