!------------------------------------------------------------------------------
!
!  Program name:
!
!    generic_maxabs   
!
!  Purpose:
!
!    This program demonstrates how to define a generic procedure for 
!    finding the maximum absolute value using external procedures.
!
!------------------------------------------------------------------------------

PROGRAM generic_maxabs

  IMPLICIT NONE
  REAL :: a, b
  INTEGER :: ia, ib
  COMPLEX :: ca, cb

  INTERFACE maxabs              ! generic name
    REAL FUNCTION maxabsreal(u,v)
      REAL, INTENT(IN) :: u, v
    END FUNCTION maxabsreal

    INTEGER FUNCTION maxabsint(u,v)
      INTEGER, INTENT(IN) :: u, v
    END FUNCTION maxabsint

    REAL FUNCTION maxabscpx(u,v)
      COMPLEX, INTENT(IN) :: u, v
    END FUNCTION maxabscpx
  END INTERFACE

  ! maxabs two reals
  a = 1.0
  b = -2.0
  WRITE(*,*) 'Real values are          : ', a, b
  WRITE(*,*) 'Maximum absolute value is: ', maxabs(a,b)
  WRITE(*,*)

  ! maxabs two integers
  ia = 1
  ib = -2
  WRITE(*,*) 'Integer values are       : ', ia, ib
  WRITE(*,*) 'Maximum absolute value is: ', maxabs(ia,ib)
  WRITE(*,*)

  ! maxabs two complex
  ca = (1.0, 1.0)
  cb = (-2.0, -2.0)
  WRITE(*,*) 'Complex values are:       : ', ca, cb
  WRITE(*,*) 'Maximum absolute value is : ', maxabs(ca,cb)
  WRITE(*,*)

END PROGRAM generic_maxabs

REAL FUNCTION maxabsreal(u,v)   ! external procedure for real maxabs

  IMPLICIT NONE
  REAL, INTENT(IN) :: u, v

  maxabsreal = MAX(ABS(u),ABS(v))

END FUNCTION maxabsreal

INTEGER FUNCTION maxabsint(u,v)	! external procedure for integer maxabs

  IMPLICIT NONE
  INTEGER, INTENT(IN) :: u, v

  maxabsint = MAX(ABS(u),ABS(v))

END FUNCTION maxabsint

REAL FUNCTION maxabscpx(u,v)    ! external procedure complex maxabs

  IMPLICIT NONE
  COMPLEX, INTENT(IN) :: u, v

  maxabscpx = MAX(ABS(u),ABS(v))

END FUNCTION maxabscpx
