module dc_present

  !------------------------------------------------------
  ! to judge optional control parameters
  !------------------------------------------------------

  use dc_types, only: DP, SP, INT, TOKEN, STRING
  private
  public :: present_and_true
  public :: present_and_false
  public :: present_and_zero
  public :: present_and_nonzero
  public :: present_and_eq
  public :: present_and_ne
  public :: present_and_not_empty

  interface present_and_eq
     module procedure present_and_eq_integer
     module procedure present_and_eq_real
     module procedure present_and_eq_double
!!$#ifndef NO_DOUBLE
!!$     module procedure present_and_eq_double
!!$#endif
  end interface
  interface present_and_ne
     module procedure present_and_ne_integer
     module procedure present_and_ne_real
     module procedure present_and_ne_double
!!$#ifndef NO_DOUBLE
!!$     module procedure present_and_ne_double
!!$#endif
  end interface

contains

  function present_and_true(arg) result(result)
    logical :: result
    logical,intent(in),optional :: arg
    if(present(arg)) then
       if(arg) then
          result=.true.
       else
          result=.false.
       endif
    else
       result=.false.
    endif
  end function present_and_true

  function present_and_false(arg) result(result)
    logical :: result
    logical,intent(in),optional :: arg
    if(present(arg)) then
       if(arg) then
          result=.false.
       else
          result=.true.
       endif
    else
       result=.false.
    endif
  end function present_and_false

  function present_and_zero(arg) result(result)
    logical :: result
    integer(INT),intent(in),optional :: arg
    if(present(arg)) then
       if(arg==0) then
          result=.true.
       else
          result=.false.
       endif
    else
       result=.false.
    endif
  end function present_and_zero

  function present_and_nonzero(arg) result(result)
    logical :: result
    integer(INT),intent(in),optional :: arg
    if(present(arg)) then
       if(arg==0) then
          result=.false.
       else
          result=.true.
       endif
    else
       result=.false.
    endif
  end function present_and_nonzero

  function present_and_eq_integer(arg,val) result(result)
    logical :: result
    integer(INT),intent(in),optional :: arg
    integer(INT),intent(in) :: val
    if(present(arg)) then
       if(arg==val) then
          result=.true.
       else
          result=.false.
       endif
    else
       result=.false.
    endif
  end function present_and_eq_integer

  function present_and_eq_real(arg,val) result(result)
    logical :: result
    real(SP),intent(in),optional :: arg
    real(SP),intent(in) :: val
    if(present(arg)) then
       if(arg==val) then
          result=.true.
       else
          result=.false.
       endif
    else
       result=.false.
    endif
  end function present_and_eq_real

  function present_and_eq_double(arg,val) result(result)
    logical :: result
    real(DP),intent(in),optional :: arg
    real(DP),intent(in) :: val
    if(present(arg)) then
       if(arg==val) then
          result=.true.
       else
          result=.false.
       endif
    else
       result=.false.
    endif
  end function present_and_eq_double

  function present_and_ne_integer(arg,val) result(result)
    logical :: result
    integer(INT),intent(in),optional :: arg
    integer(INT),intent(in) :: val
    if(present(arg)) then
       if(arg/=val) then
          result=.true.
       else
          result=.false.
       endif
    else
       result=.false.
    endif
  end function present_and_ne_integer

  function present_and_ne_real(arg,val) result(result)
    logical :: result
    real(SP),intent(in),optional :: arg
    real(SP),intent(in) :: val
    if(present(arg)) then
       if(arg/=val) then
          result=.true.
       else
          result=.false.
       endif
    else
       result=.false.
    endif
  end function present_and_ne_real

  function present_and_ne_double(arg,val) result(result)
    logical :: result
    real(DP),intent(in),optional :: arg
    real(DP),intent(in) :: val
    if(present(arg)) then
       if(arg/=val) then
          result=.true.
       else
          result=.false.
       endif
    else
       result=.false.
    endif
  end function present_and_ne_double

  function present_and_not_empty(arg) result(result)
    logical :: result
    character(len=*),intent(in),optional :: arg
    if(present(arg)) then
       if(arg=="") then
          result=.false.
       else
          result=.true.
       endif
    else
       result=.false.
    endif
  end function present_and_not_empty

end module dc_present
