  PROGRAM test
  USE set_precision, ONLY: dp=>dkind, sp=>skind
  USE oracle, ONLY:initialize, RandVec, TestVec, VecOracle, &
                   dpOverFlow, spOverFlow, Errors, GenTestVec, &
                   randomInt
  
  REAL(KIND=dp) :: dpX(5), dpLow, dpHigh, dpNorm
  REAL(KIND=dp), PARAMETER :: hugeDp = HUGE(0.0e0_dp)
  REAL(KIND=sp) :: spX(5), spLow, spHigh, spNorm, spRel, spUlps, &
                   dpUlps, dpRel
  REAL(KIND=sp), PARAMETER :: hugeSp = HUGE(0.0e0_sp)

  LOGICAL, ALLOCATABLE :: check(:)
  LOGICAL :: allSet

  INTEGER, PARAMETER :: minExp = -1022
  INTEGER, PARAMETER :: maxExp = 1023
  INTEGER, PARAMETER :: nRands = 50000

  CALL initialize(.TRUE.)

! Test out randomInt
  ALLOCATE (check(minExp:maxExp))
  check(:) = .FALSE.
  DO i = 1, nRands
    ir = randomInt(minExp, maxExp)
    check(ir) = .TRUE.
  END DO
  allSet = .TRUE.
  DO i = minExp, maxExp
    IF(.NOT.check(ir)) THEN
      IF (allSet) THEN
        write(*,'(a, i3, a)') &
          'RandomInt function may not be performing correctly'
        allSet = .FALSE.
      END IF
      write(*,'(a, i3, a)') 'check(',ir,') not set'
    END IF
  END DO
  IF (allSet) THEN
        write(*,'(a, i3, a)') &
          'RandomInt function appears correct'
  END IF
    
  DEALLOCATE (check)

  write(*,'(a)')  'Simple test of oracle routines'
  write(*,*)
  write(*,'(a)')  'Double Precision routines:'
  write(*,*)

  dpLow = 1.0E0_dp
  dpHigh = 6.0E0_dp
  CALL RandVec(dpX)
  write(*,'(a)')  'DpVec (0,1)'
  write(*,'(4e16.8)')  dpX(:)
  dpNorm = norm2(dpX)
  CALL VecOracle(dpX)
  CALL Errors(dpNorm, dpRel, dpUlps)
  write(*,'(a,3e14.6/)')  'Errors: ', dpNorm, dpRel, dpUlps

  CALL TestVec(dpX, dpLow, dpHigh)
  write(*,'(a,e16.8,a,e16.8,a)') &
       'DpVec ( ', dpLow, ', ', dpHigh, ')'
  write(*,'(4e16.8)')  dpX(:)
  dpNorm = norm2(dpX)
  CALL VecOracle(dpX)
  CALL Errors(dpNorm, dpRel, dpUlps)
  write(*,'(a,3e14.6)')  'Errors: ', dpNorm, dpRel, dpUlps

! Test that the overflag is being correctly set in vecOracle
! set range of vector values to (huge/2, huge) then a vector
! of length 5 will guarantee to overflow.
  dpLow = hugeDp/2.0e0_dp
  dpHigh = hugeDp
  CALL TestVec(dpX, dpLow, dpHigh)
  CALL VecOracle(dpX)
  write(*,*)
  write(*,'(a)') 'Test overflow condition trapped'
  IF (dpOverFlow) THEN
    write(*,'(a)')  'dpOverFlow correctly set'
  ELSE
    write(*,'(a)')  'dpOverFlow has NOT been correctly set'
  END IF

  write(*,*)
  write(*,'(a)')  '=============================================='
  write(*,*)
  write(*,'(a)')  'Single Precision routines:'
  write(*,*)

  spLow = 3.0E0_sp
  spHigh = 10.0E0_sp
  CALL RandVec(spX)
  write(*,'(a)')  'spVec (0,1)'
  write(*,'(5e12.4)')  spX(:)
  spNorm = norm2(spX)
  CALL VecOracle(spX)
  CALL Errors(spNorm, spRel, spUlps)
  write(*,'(a,3e12.4/)')  'Errors: ', spNorm, spRel, spUlps
  CALL TestVec(spX, spLow, spHigh)
  write(*,'(a,e16.8,a,e16.8,a)') &
       'SpVec ( ', spLow, ', ', spHigh, ')'
  write(*,'(5e12.4)')  spX(:)
  spNorm = norm2(spX)
  CALL VecOracle(spX)
  CALL Errors(spNorm, spRel, spUlps)
  write(*,'(a,3e12.4)')  'Errors: ', spNorm, spRel, spUlps

! Test that the overflag is being correctly set in vecOracle
! set range of vector values to (huge/2, huge) then a vector
! of length 5 will guarantee to overflow.
  spLow = hugesp/2.0e0_sp
  spHigh = hugesp
  CALL TestVec(spX, spLow, spHigh)
  CALL VecOracle(spX)
  write(*,*)
  write(*,'(a)') 'Test overflow condition trapped'
  IF (spOverFlow) THEN
    write(*,'(a)')  'spOverFlow correctly set'
  ELSE
    write(*,'(a)')  'spOverFlow has NOT been correctly set'
  END IF

  END PROGRAM test
