PROGRAM precision_11
	IMPLICIT NONE

	! This program shows how increased precision may be obtained by 
	! using an increased range of integers or more significant figures 
	! and increase exponent range for real numbers.

	INTEGER :: int0
	REAL :: real0
	INTEGER, PARAMETER :: dp = KIND(1.0d0)
	REAL(dp) :: real1, real2
	INTEGER, PARAMETER :: real_15_300=SELECTED_REAL_KIND(P=15,R=300)
	REAL(real_15_300) :: real3, real4


!----------------------------------------------------------------------------
! 1. Default type integers. The default type (KIND) is usually sufficient. 

	! Example of a default-declared integer, 
	! checking its kind (=4 here) using the KIND intrinsic function, and 
	! finding the largest integer of this kind.
	! Usually this will be a 32 bit representation

	int0 = 343434343
	
	PRINT*
	PRINT*, 'The default integers on this computer: '
	PRINT*
	PRINT*, 'int0 = ',int0,'  kind = ',KIND(int0),  'largest = ',HUGE(int0)
	PRINT*

!----------------------------------------------------------------------------
! 2. Default-type real numbers (single precision).

	! Real numbers are represented by the 
	! PRECISION P (number of decimal places, usually 8) and the 
	! RANGE R(maximum exponent in powers of 10, usually 38)
	! For historical reasons, this is often called `single precision'

	real0 = 0.12345678987654321e31

	! Also note how the largest (HUGE(real0)) and smallest (TINY(real0)) 
	! numbers of same type as real0 can be obtained.
	! The machine epsilon (EPSILON(real0)) is the smallest number which 
	! when added to one returns a number different from one.

	PRINT*
	PRINT*, 'Default real numbers:'
	PRINT*
	PRINT*, 'real0 = ',real0
	PRINT*, 'kind = ',KIND(real0)
	PRINT*, 'huge = ',HUGE(real0)
	PRINT*, 'tiny = ',TINY(real0)
	PRINT*, 'machine epsilon = ',EPSILON(real0)
	PRINT*

!--------------------------------------------------------------------------
! 3. Double precision real numbers.

	! You should be aware that all real number calculations on a computer 
	! are only ever approximate.
	! You will frequently want more precision that is provided by the 
	! default single precision reals. 

	! The kind type (here dp) must be attached to the end of constants. 
	! (Usually these will be KIND=8 so that, alternatively, _8 may be 
	! appended - although this would be less portable)

	real1 = 0.12345678987654321e-20_dp

	! Observe what happens if this is omitted (treated as default real)
	! is truncated accordingly, and when assigned to real2 (double 
	! precision) has lower order decimal places reinserted but which 
	! now correspond to a different number.

	real2 = 0.12345678987654321e-20

	PRINT*
	PRINT*, 'Kind=8 real numbers (double precision):'
	PRINT*
	PRINT*, 'real1 = ',real1
	PRINT*, 'real2 = ',real2
	PRINT*, 'kind = ',KIND(real1)
	PRINT*, 'huge = ',HUGE(real1)
	PRINT*, 'tiny = ',TINY(real1)
	PRINT*, 'machine epsilon = ',EPSILON(real1)
	PRINT*

!--------------------------------------------------------------------------
! 3. Guaranteed minimum precision real numbers.

	! You may want to ensure that, on porting your program to another 
	! computer, that a minimum level of precision is maintained. 
	! This can be ensured by specifying a precision P and exponent range 
	! which will be the minimum values used providied the computer can 
	! support it. 

	real3 = 0.12345678987654321e-20_real_15_300

	! Observe what happens if the real_15_300 is omitted - see previous 
	! example. This notation is unwieldy: stick to `dp' above.

	real4 = 0.12345678987654321e-20

	PRINT*
	PRINT*, 'Kind=8 real numbers (double precision):'
	PRINT*
	PRINT*, 'real3 = ',real3
	PRINT*, 'real4 = ',real4
	PRINT*, 'kind = ',KIND(real3)
	PRINT*, 'huge = ',HUGE(real3)
	PRINT*, 'tiny = ',TINY(real3)
	PRINT*, 'machine epsilon = ',EPSILON(real3)
	PRINT*



END PROGRAM precision_11
