module gFTL_StringVector

      implicit none

      integer, parameter :: SIZE_KIND =                                        &
     &           max(kind(1),selected_int_kind(18))

      type Unusable
      end type Unusable

      private

      public :: StringVector
      public :: StringVectorIterator
      public :: StringVectorRIterator
      public :: swap

      type :: v_Wrapper
         character(len=:) , allocatable :: item
      end type v_Wrapper

      type :: StringVector
         private
         type(v_Wrapper), allocatable :: elements(:)
         integer(kind=SIZE_KIND) :: vsize = 0
      contains
         procedure :: size => v_size
         procedure :: capacity => v_capacity
         procedure :: empty => v_empty

         procedure :: at_size_kind => v_at_size_kind
         generic :: at => at_size_kind

         procedure :: at_32 => v_at_32
         generic :: at => at_32

         procedure :: of => v_of
         procedure :: get_size_kind => v_get_size_kind
         generic :: get => get_size_kind

         procedure :: get_32 => v_get_32
         generic :: get => get_32

         procedure :: back => v_back
         procedure :: front => v_front

         procedure :: set_size_kind => v_set_size_kind
         generic :: set => set_size_kind

         procedure :: set_32 => v_set_32
         generic :: set => set_32

         procedure :: push_back => v_push_back
         procedure :: pop_back => v_pop_back
         procedure :: insert_size_kind => v_insert_size_kind
         generic :: insert => insert_size_kind

         procedure :: insert_32 => v_insert_32
         generic :: insert => insert_32

         procedure :: resize_size => v_resize_size
         generic :: resize => resize_size

         procedure :: resize_32 => v_resize_32
         generic :: resize => resize_32

         procedure :: clear => v_clear
         procedure :: shrink_to_fit => v_shrink_to_fit

         procedure :: v_erase_one
         procedure :: v_erase_range
         generic :: erase => v_erase_one, v_erase_range

         procedure :: reserve_size_kind => v_reserve_size_kind
         generic :: reserve => reserve_size_kind

         procedure :: reserve_32 => v_reserve_32
         generic :: reserve => reserve_32

         procedure :: swap => v_swap
         procedure :: reset => v_reset

         procedure :: get_index => v_get_index
         procedure :: equal => v_equal
         procedure :: not_equal => v_not_equal
         generic :: operator(==) => equal
         generic :: operator(/=) => not_equal

         procedure, private :: diff=>v_diff
         procedure :: less_than => v_less_than
         procedure :: greater_than_or_equal_to =>                        &
     &      v_greater_than_or_equal_to
         generic :: operator(<) => less_than
         generic :: operator(>=) => greater_than_or_equal_to

         procedure :: greater_than => v_greater_than
         procedure :: less_than_or_equal_to =>                           &
     &      v_less_than_or_equal_to
         generic :: operator(>) => greater_than
         generic :: operator(<=) => less_than_or_equal_to

         procedure :: begin => v_begin
         procedure :: end => v_end

         procedure :: rbegin => v_rbegin
         procedure :: rend => v_rend

         procedure, private :: set_capacity => v_set_capacity
         procedure, private :: grow_to => v_grow_to
         procedure, private :: downsize=>v_downsize
      end type StringVector

      interface StringVector
         module procedure v_new_empty
      end interface StringVector

      interface swap
         module procedure v_swap
      end interface swap

      type StringVectorIterator
         private

         type(v_Wrapper), dimension(:), pointer :: elements
         integer(kind=SIZE_KIND) :: currentIndex = -1 ! intentionally invalid value

      contains

         procedure :: get => v_iter_get
         procedure :: next => v_iter_next
         procedure :: previous => v_iter_previous
         procedure :: v_iter_atDefault
         generic :: at => v_iter_atDefault
         procedure :: v_iter_atOffset
         generic :: at => v_iter_atOffset

         procedure :: v_iter_atOffset_32
         generic :: at => v_iter_atOffset_32

         procedure :: v_iter_equal
         procedure ::  v_not_iter_equal
         generic :: operator(==) => v_iter_equal
         generic :: operator(/=) => v_not_iter_equal

         procedure :: v_iter_less
         procedure :: v_iter_less_equal
         procedure :: v_iter_greater
         procedure :: v_iter_greater_equal
         generic :: operator(<) => v_iter_less
         generic :: operator(<=) => v_iter_less_equal
         generic :: operator(>) => v_iter_greater
         generic :: operator(>=) => v_iter_greater_equal

         procedure :: v_iter_add
         procedure :: v_iter_subtract
         generic :: operator(+) => v_iter_add
         generic :: operator(-) => v_iter_subtract

         procedure :: v_iter_add_32
         procedure :: v_iter_subtract_32
         generic :: operator(+) => v_iter_add_32
         generic :: operator(-) => v_iter_subtract_32

      end type StringVectorIterator

      type StringVectorRIterator
         private

         type(v_Wrapper), dimension(:), pointer :: elements
         integer(kind=SIZE_KIND) :: currentIndex = -1 ! intentionally invalid value

      contains

         procedure :: get => v_riter_get
         procedure :: next => v_riter_next
         procedure :: previous => v_riter_previous

         procedure :: v_riter_atDefault
         generic :: at => v_riter_atDefault
         procedure :: v_riter_atOffset
         generic :: at => v_riter_atOffset

         procedure :: v_riter_atOffset_32
         generic :: at => v_riter_atOffset_32

         procedure :: v_riter_equal
         procedure :: v_riter_not_equal
         generic :: operator(==) => v_riter_equal
         generic :: operator(/=) => v_riter_not_equal

         procedure :: v_riter_less
         procedure :: v_riter_less_equal
         procedure :: v_riter_greater
         procedure :: v_riter_greater_equal
         generic :: operator(<) => v_riter_less
         generic :: operator(<=) => v_riter_less_equal
         generic :: operator(>) => v_riter_greater
         generic :: operator(>=) => v_riter_greater_equal

         procedure :: v_riter_add
         procedure :: v_riter_subtract
         generic :: operator(+) => v_riter_add
         generic :: operator(-) => v_riter_subtract

         procedure :: v_riter_add_32
         procedure :: v_riter_subtract_32
         generic :: operator(+) => v_riter_add_32
         generic :: operator(-) => v_riter_subtract_32

      end type StringVectorRIterator

      integer, parameter :: SUCCESS = 0
      integer, parameter :: OUT_OF_RANGE = 1
      integer, parameter :: BAD_ALLOC = 2
      integer, parameter :: ILLEGAL_INPUT = 3

      type :: KeywordEnforcer
      end type KeywordEnforcer

      contains

      function v_new_empty() result(v)
         type (StringVector) :: v
         logical, parameter :: flag = .false.
         if (flag) print*,shape(v) ! avoid warning about unused return value
         return
      end function v_new_empty

      pure function v_size(this) result(res)
         class(StringVector), intent(in) :: this
         integer(kind=SIZE_KIND) :: res

         res=this%vsize
         return
      end function v_size

      pure function v_capacity(this) result(capacity)
         integer(kind=SIZE_KIND) :: capacity
         class (StringVector), intent(in) :: this

         if (allocated(this%elements)) then
            capacity = size(this%elements)
         else
            capacity = 0
         end if

      end function v_capacity

      pure logical function v_empty(this) result(empty)
         class(StringVector), intent(in) :: this

         empty = this%vsize==0

      end function v_empty

      function v_at_size_kind(this, i, unused, rc) result(res)
         class(StringVector), target, intent(in) :: this
         integer(KIND=SIZE_KIND), intent(in) :: i
         type (KeywordEnforcer), optional, intent(in) :: unused
         integer, optional, intent(out) :: rc
         character(len=:) , pointer :: res

         if (.false.) print*,shape(unused)

         if ((i<=0).or.(i>this%vsize)) then
            if (present(rc)) rc = OUT_OF_RANGE
            return
         end if

         res=>this%elements(i)%item
         return
      end function v_at_size_kind

      function v_at_32(this, i, unused, rc) result(res)
         class(StringVector), target, intent(in) :: this
         integer, intent(in) :: i
         character(len=:) , pointer :: res
         type (KeywordEnforcer), optional, intent(in) :: unused
         integer, optional, intent(out) :: rc

         if (.false.) print*,shape(unused)

         res => this%at_size_kind(int(i,kind=SIZE_KIND),rc=rc)

      end function v_at_32

      function v_of(this, i) result(res)
         class(StringVector), target, intent(in) :: this
         integer, intent(in) :: i
         character(len=:) , pointer :: res

         res=>this%elements(i)%item
         return
      end function v_of

      function v_get_size_kind(this, i) result(res)
         class(StringVector), target, intent(in) :: this
         integer(kind=SIZE_KIND), intent(in) :: i
         character(len=:) , allocatable :: res
         integer(kind=SIZE_KIND) :: idx

         idx=merge(i, this%vsize+i, i>0)
         res=this%elements(idx)%item

      end function v_get_size_kind

      function v_get_32(this, i) result(res)
         class(StringVector), target, intent(in) :: this
         integer, intent(in) :: i
         character(len=:) , allocatable :: res

         integer(kind=SIZE_KIND) :: idx
         integer(kind=SIZE_KIND) :: i64
         i64 = int(i,kind=SIZE_KIND)
         idx=merge(i64, this%vsize+i64, i64>0)
         res=this%elements(idx)%item

      end function v_get_32

      function v_back(this) result(res)
         class(StringVector), target, intent(in) :: this
         character(len=:) , pointer :: res

         res=>this%elements(this%vsize)%item
         return
      end function v_back

      function v_front(this) result(res)
         class(StringVector), target, intent(in) :: this
         character(len=:) , pointer :: res

         res=>this%elements(1)%item
         return
      end function v_front

      subroutine v_set_size_kind(this, i, value)
         class(StringVector), intent(inout) :: this
         integer(kind=SIZE_KIND), intent(in) :: i
         character(len=*) , intent(in) :: value

         integer(kind=SIZE_KIND) :: idx

         idx=merge(i, this%vsize+i, i>0)

         deallocate(this%elements(idx)%item)
         this%elements(idx)%item=value
         return
      end subroutine v_set_size_kind

      subroutine v_set_32(this, i, value)
         class(StringVector), intent(inout) :: this
         integer, intent(in) :: i
         character(len=*) , intent(in) :: value

         call this%set(int(i,kind=SIZE_KIND), value)

      end subroutine v_set_32

      subroutine v_reset(this)
         class(StringVector), intent(inout) :: this

         if (allocated(this%elements)) then
            deallocate(this%elements)
         end if
         this%vsize=0
         return
      end subroutine v_reset

      function v_get_index(this, value) result(i)
         class(StringVector), target, intent(in) :: this
         character(len=*) , intent(in) :: value
         integer(kind=SIZE_KIND) :: i

         do i=1, this%vsize
            if ((this%elements(i)%item == value)) return
         end do
         i=0
         return
      end function v_get_index

       function                                                            & 
     &          v_equal(this, other) result(equal)
         logical :: equal
         class(StringVector), intent(in) :: this, other
         integer :: i

         equal = (this%vsize == other%vsize) 
         if (equal) then
            equal = .false.
            do i = 1, this%vsize

       if (.not.                                                                              &
     &    (this%elements(i)%item == other%elements(i)%item))                        &
     &       return

            end do
            equal = .true.
         endif

      end function v_equal

       function                                                            &
     &        v_not_equal(this, other) result (not_equal)
         logical :: not_equal
         class(StringVector), intent(in) :: this, other

         not_equal = .not. (this == other)

         return
      end function v_not_equal

       function                                                          &
     &     v_diff(a, b, less) result(diff)
         class(StringVector), intent(in) :: a
         class(StringVector), intent(in) :: b
         logical, intent(in) :: less
         logical :: diff
         integer :: i, n

         character(len=:) , pointer :: ai, bi

         n=min(a%size(), b%size())
         do i=1, n
            ai => a%of(i)
            bi => b%of(i)
           if ((ai)<(bi)) then
             diff=less
             return
           else if ((bi)<(ai)) then
             diff=.not.less
             return
           endif
         end do
         diff=merge(a%size()<b%size(), b%size()<a%size(), less)
         return
      end function v_diff

       function                                                          &
     &     v_less_than(a, b) result(less_than)
         logical :: less_than
         class (StringVector), intent(in) :: a
         class (StringVector), intent(in) :: b

         less_than=v_diff(a, b, .true.)
         return
      end function v_less_than

       function                                                                 &
     &       v_greater_than_or_equal_to(a, b)                                &
     &       result(greater_than_or_equal_to)
         logical :: greater_than_or_equal_to
         class (StringVector), intent(in) :: a
         class (StringVector), intent(in) :: b

         greater_than_or_equal_to=.not.v_diff(a, b, .true.)
         return
      end function v_greater_than_or_equal_to

       function                                                                 &
     &                 v_greater_than(a, b) result(greater_than)
         logical :: greater_than
         class (StringVector), intent(in) :: a
         class (StringVector), intent(in) :: b

         greater_than=v_diff(a, b, .false.)
         return
       end function v_greater_than

       function                                                             &
     &  v_less_than_or_equal_to(a, b)                                                   &
     &  result(less_than_or_equal_to)
         logical :: less_than_or_equal_to
         class (StringVector), intent(in) :: a
         class (StringVector), intent(in) :: b

         less_than_or_equal_to=.not.v_diff(a, b, .false.)
         return
      end function v_less_than_or_equal_to

      subroutine v_push_back(this, value, unused, rc)
         class(StringVector), intent(inout) :: this
         character(len=*) , intent(in) :: value
         type (KeywordEnforcer), optional, intent(in) :: unused
         integer, optional, intent(out) :: rc

         if (.false.) print*,shape(unused)

         call this%grow_to(this%vsize+1)
         call this%resize(this%vsize+1, value, rc=rc)
         return

      end subroutine v_push_back

      subroutine v_pop_back(this)
         class(StringVector), intent(inout) :: this

         call this%downsize(this%vsize-1)
         return
      end subroutine v_pop_back

      subroutine v_insert_size_kind(                                                 &
     &   this, index, value, unused, rc)
         class(StringVector), target, intent(inout) :: this

         integer(kind=SIZE_KIND), intent(in) :: index

         character(len=*) , intent(in) :: value
         type (KeywordEnforcer), optional, intent(in) :: unused
         integer, optional, intent(out) :: rc

         character(len=:) , allocatable :: temp
         integer(kind=SIZE_KIND) :: i, n

         if (.false.) print*,shape(unused)

         n = this%vsize
         if (index==n+1) then
            call this%push_back(value)
            temp=value
            return
         endif
         call this%grow_to(this%vsize+1)
         temp=this%elements(n)%item
         call this%resize(n+1, temp, rc=rc)

         do i = n, index, -1
          call move_alloc(from=this%elements(i)%item, to=this%elements(i+1)%item)
         end do

         this%elements(index)%item=value

         return
      end subroutine v_insert_size_kind

      subroutine v_insert_32(this, index, value)
         class(StringVector), intent(inout) :: this
         integer, intent(in) :: index
         character(len=*) , intent(in) :: value

         call this%insert(int(index,kind=SIZE_KIND), value)
      end subroutine v_insert_32

      subroutine v_resize_size(this, newsize, value, unused, rc)
         class(StringVector), intent(inout) :: this
         integer(kind=SIZE_KIND), intent(in) :: newsize
         character(len=*) , optional, intent(in) :: value
         type (KeywordEnforcer), optional, intent(in) :: unused
         integer, optional, intent(out) :: rc

         integer(kind=SIZE_KIND) :: oldSize
         integer(kind=SIZE_KIND) :: i

         if (.false.) print*,shape(unused)

         if (newSize == this%vsize) return
         if (newSize < 0) then
            if (present(rc)) rc = ILLEGAL_INPUT
            return
         end if
         oldSize=this%vsize

         call this%reserve(newSize)
         this%vsize = newSize

         do i = newSize + 1, oldSize
            deallocate(this%elements(i)%item)
         end do

         if (present(value) .and. (newsize>oldsize)) then
            do i = oldSize + 1, newSize
               this%elements(i)%item=value
            end do
         endif
         return
      end subroutine v_resize_size

      subroutine v_resize_32(this, newsize, value, unused, rc)
         class(StringVector), intent(inout) :: this
         integer, intent(in) :: newsize
         character(len=*) , optional, intent(in) :: value
         type (KeywordEnforcer), optional, intent(in) :: unused
         integer, optional, intent(out) :: rc

         if (.false.) print*,shape(unused)

         call this%resize(int(newsize,kind=SIZE_KIND), value, rc=rc)

      end subroutine v_resize_32

      subroutine v_downsize(this, newsize)
         class(StringVector), intent(inout) :: this
         integer(kind=SIZE_KIND), intent(in) :: newsize  ! assumes newsize<=size()
         integer(kind=SIZE_KIND) :: i

         if (newsize<this%vsize) then
           do i=newsize+1, this%vsize
              deallocate(this%elements(i)%item)
           end do
           this%vsize=newsize
         endif

         return
      end subroutine v_downsize

      subroutine v_clear(this)
         class(StringVector), intent(inout) :: this

         call this%downsize(0_SIZE_KIND)

         return
      end subroutine v_clear

      subroutine v_shrink_to_fit(this)
         class(StringVector), intent(inout) :: this

         if (this%vsize<this%capacity()) then
           call this%set_capacity(this%vsize)
         endif
         return
      end subroutine v_shrink_to_fit

      subroutine v_erase_one(this, position)
         class(StringVector), target, intent(inout) :: this
         type (StringVectorIterator), intent(in)  :: position

         call this%erase(position, position+1)

         return
      end subroutine v_erase_one

      subroutine v_erase_range(this, first, last)
         class(StringVector), target, intent(inout) :: this
         type (StringVectorIterator), intent(in)  :: first
         type (StringVectorIterator), intent(in)  :: last

         integer :: i, delta

         delta=last%currentindex-first%currentindex
         do i=last%currentIndex, this%vsize
            associate(a => this%elements(i-delta),b =>this%elements(i))
              call move_alloc(from=b%item, to=a%item)
            end associate
         end do
         do i = this%vsize - delta + 1, last%currentIndex - 1
            deallocate(this%elements(i)%item)
         end do
         this%vsize=this%vsize-delta

         return
      end subroutine v_erase_range

      subroutine v_reserve_size_kind(this, capacity)
         class(StringVector), intent(inout) :: this
         integer(kind=SIZE_KIND), intent(in) :: capacity

         if (capacity>this%capacity()) then
           call this%set_capacity(capacity)
         endif

         return
      end subroutine v_reserve_size_kind

      subroutine v_reserve_32(this, capacity)
         class(StringVector), intent(inout) :: this
         integer, intent(in) :: capacity

         call this%reserve(int(capacity,kind=SIZE_KIND))
         return
      end subroutine v_reserve_32

      subroutine v_set_capacity(this, capacity)
         class(StringVector), target, intent(inout) :: this
         integer(kind=SIZE_KIND), intent(in) :: capacity  ! capacity must be >=0
         type(v_Wrapper),dimension(:),allocatable,target :: temp
         integer(kind=SIZE_KIND) :: i

         if (capacity>0) then                     ! capacity>0
           if (.not.allocated(this%elements)) then   ! not allocated
             allocate(this%elements(capacity))
           else                                      ! allocated
             allocate(temp(capacity))
             do i=1, this%vsize
               call move_alloc(from=this%elements(i)%item, to=temp(i)%item)
             end do
             deallocate(this%elements)
             call move_alloc(temp, this%elements)
           endif
         else if (allocated(this%elements)) then  ! capacity==0
            deallocate(this%elements)
         endif

         return
      end subroutine v_set_capacity

      subroutine v_grow_to(this, capacity)
         class(StringVector), intent(inout) :: this
         integer(kind=SIZE_KIND), intent(in) :: capacity

         if (capacity>this%capacity()) then
           call this%set_capacity(max(2*this%vsize, capacity)) ! gives O(n) algorithm for growing vector with push.
         endif
         return
      end subroutine v_grow_to

      subroutine v_swap(this, other)
         class(StringVector), target, intent(inout) :: this
         type(StringVector), target, intent(inout) :: other
         type(v_Wrapper),                                                                &
     &           dimension(:), allocatable :: tmpelementsfer
         integer :: tmpsize

         call move_alloc(this%elements, tmpelementsfer)
         call move_alloc(other%elements, this%elements)
         call move_alloc(tmpelementsfer, other%elements)
         tmpsize=this%vsize
         this%vsize=other%vsize
         other%vsize=tmpsize
         return
      end subroutine v_swap

      function v_begin(this) result(iter)
         type (StringVectorIterator) :: iter
         class (StringVector), target, intent(in) :: this

         iter%currentIndex = 1
         if (allocated(this%elements)) then
            iter%elements => this%elements
         else
            iter%elements => null()
         end if

      end function v_begin

      function v_end(this) result(iter)
         class (StringVector), target, intent(in) :: this
         type (StringVectorIterator) :: iter

         iter%currentIndex = this%size() + 1 ! past the end
         if (allocated(this%elements)) then
            iter%elements => this%elements
         else
            iter%elements => null()
         end if

      end function v_end

      function v_rbegin(this) result(iter)
         type (StringVectorRIterator) :: iter
         class (StringVector), target, intent(in) :: this

         iter%currentIndex = this%vsize
         if (allocated(this%elements)) then
            iter%elements => this%elements
         else
            iter%elements => null()
         end if

      end function v_rbegin

      function v_rend(this) result(iter)
         class (StringVector), target, intent(in) :: this
         type (StringVectorRIterator) :: iter

         iter%currentIndex = 0 ! before beginning
         if (allocated(this%elements)) then
            iter%elements => this%elements
         else
            iter%elements => null()
         end if

      end function v_rend

      function v_iter_get(this) result (item)
         class (StringVectorIterator), intent(in) :: this

         character(len=:) , pointer :: item
         item => this%elements(this%currentIndex)%item

      end function v_iter_get

      subroutine v_iter_next(this)
         class (StringVectorIterator), intent(inout) :: this
         this%currentIndex = this%currentIndex + 1
      end subroutine v_iter_next

      subroutine v_iter_previous(this)
         class (StringVectorIterator), intent(inout) :: this
         this%currentIndex = this%currentIndex - 1
      end subroutine v_iter_previous

      logical function v_iter_equal(this, other) result(eq)
         class (StringVectorIterator), intent(in) :: this
         class (StringVectorIterator), intent(in) :: other

         eq = (this%currentIndex == other%currentIndex)

      end function v_iter_equal

      logical function v_not_iter_equal(this, other) result(ne)
         class (StringVectorIterator), intent(in) :: this
         class (StringVectorIterator), intent(in) :: other

         ne = .not. (this == other)

      end function v_not_iter_equal

      logical function v_iter_less(this, other) result(less)
         class (StringVectorIterator), intent(in) :: this
         class (StringVectorIterator), intent(in) :: other
         less = (this%currentIndex < other%currentIndex)
      end function v_iter_less

      function v_iter_less_equal(this,other) result(le)
         logical :: le
         class (StringVectorIterator), intent(in) :: this
         class (StringVectorIterator), intent(in) :: other
         le = (this%currentIndex <= other%currentIndex)
      end function v_iter_less_equal

      logical function v_iter_greater(this, other) result(gt)
         class (StringVectorIterator), intent(in) :: this
         class (StringVectorIterator), intent(in) :: other
         gt = (this%currentIndex > other%currentIndex)
      end function v_iter_greater

      function v_iter_greater_equal(this,other) result(gte)
         logical :: gte
         class (StringVectorIterator), intent(in) :: this
         class (StringVectorIterator), intent(in) :: other
         gte = (this%currentIndex >= other%currentIndex)
      end function v_iter_greater_equal

      function v_iter_atDefault(this) result(ptr)
         character(len=:) , pointer :: ptr
         class (StringVectorIterator), intent(in) :: this

         ptr => this%elements(this%currentIndex)%item

      end function v_iter_atDefault

      function v_iter_atOffset(this, i) result(ptr)
         character(len=:) , pointer :: ptr
         class (StringVectorIterator), intent(in) :: this
         integer(kind=SIZE_KIND), intent(in) :: i

         ptr => this%elements(this%currentIndex + i)%item

      end function v_iter_atOffset

      function v_iter_atOffset_32(this, i) result(ptr)
         character(len=:) , pointer :: ptr
         class (StringVectorIterator), intent(in) :: this
         integer, intent(in) :: i

         ptr => this%elements(this%currentIndex + i)%item

      end function v_iter_atOffset_32

      function v_iter_add(this, n) result(newIter)
         type (StringVectorIterator) :: newIter
         class (StringVectorIterator), intent(in) :: this
         integer(kind=SIZE_KIND), intent(in) :: n

         newIter%currentIndex = this%currentIndex + n
         newIter%elements => this%elements

      end function v_iter_add

      function v_iter_subtract(this, n) result(newIter)
         type (StringVectorIterator) :: newIter
         class (StringVectorIterator), intent(in) :: this
         integer(kind=SIZE_KIND), intent(in) :: n

         newIter%currentIndex = this%currentIndex - n
         newIter%elements => this%elements

      end function v_iter_subtract

      function v_iter_add_32(this, n) result(newIter)
         type (StringVectorIterator) :: newIter
         class (StringVectorIterator), intent(in) :: this
         integer, intent(in) :: n

         newIter = this + int(n,kind=SIZE_KIND)

      end function v_iter_add_32

      function v_iter_subtract_32(this, n) result(newIter)
         type (StringVectorIterator) :: newIter
         class (StringVectorIterator), intent(in) :: this
         integer, intent(in) :: n

         newIter = this - int(n,kind=SIZE_KIND)

      end function v_iter_subtract_32

      function v_riter_get(this) result (item)
         class (StringVectorRIterator), intent(in) :: this
         character(len=:) , pointer :: item
         item => this%elements(this%currentIndex)%item

      end function v_riter_get

      subroutine v_riter_next(this)
         class (StringVectorRIterator), intent(inout) :: this
         this%currentIndex = this%currentIndex - 1
      end subroutine v_riter_next

      subroutine v_riter_previous(this)
         class (StringVectorRIterator), intent(inout) :: this
         this%currentIndex = this%currentIndex + 1
      end subroutine v_riter_previous

      logical function v_riter_equal(this, other) result(eq)
         class (StringVectorRIterator), intent(in) :: this
         class (StringVectorRIterator), intent(in) :: other

         eq = (this%currentIndex == other%currentIndex)

      end function v_riter_equal

      logical function v_riter_not_equal(this,other)result(neq)
         class (StringVectorRIterator), intent(in) :: this
         class (StringVectorRIterator), intent(in) :: other

         neq = .not. (this == other)

      end function v_riter_not_equal

      function v_riter_less(this, other) result(lt)
         logical :: lt
         class (StringVectorRIterator), intent(in) :: this
         class (StringVectorRIterator), intent(in) :: other
         lt = (this%currentIndex > other%currentIndex)
      end function v_riter_less

      function v_riter_less_equal(this, other) result (lte)
         logical :: lte
         class (StringVectorRIterator), intent(in) :: this
         class (StringVectorRIterator), intent(in) :: other
         lte = (this%currentIndex >= other%currentIndex)
      end function v_riter_less_equal

      function v_riter_greater(this, other) result(gt)
         logical :: gt
         class (StringVectorRIterator), intent(in) :: this
         class (StringVectorRIterator), intent(in) :: other
         gt = (this%currentIndex < other%currentIndex)
      end function v_riter_greater

      function v_riter_greater_equal(this, other) result(gte)
         logical :: gte
         class (StringVectorRIterator), intent(in) :: this
         class (StringVectorRIterator), intent(in) :: other
         gte = (this%currentIndex <= other%currentIndex)
      end function v_riter_greater_equal

      function v_riter_atDefault(this) result(ptr)
         character(len=:) , pointer :: ptr
         class (StringVectorRIterator), intent(in) :: this

         ptr => this%elements(this%currentIndex)%item

      end function v_riter_atDefault

      function v_riter_atOffset(this, i) result(ptr)
         character(len=:) , pointer :: ptr
         class (StringVectorRIterator), intent(in) :: this
         integer(kind=SIZE_KIND), intent(in) :: i

         ptr => this%elements(this%currentIndex - i)%item

      end function v_riter_atOffset

      function v_riter_atOffset_32(this, i) result(ptr)
         character(len=:) , pointer :: ptr
         class (StringVectorRIterator), intent(in) :: this
         integer, intent(in) :: i

         ptr => this%elements(this%currentIndex - i)%item

      end function v_riter_atOffset_32

      function v_riter_add(this, n) result(newIter)
         type (StringVectorRIterator) :: newIter
         class (StringVectorRIterator), intent(in) :: this
         integer(kind=SIZE_KIND), intent(in) :: n

         newIter%currentIndex = this%currentIndex - n
         newIter%elements => this%elements

      end function v_riter_add

      function v_riter_subtract(this, n) result(newIter)
         type (StringVectorRIterator) :: newIter
         class (StringVectorRIterator), intent(in) :: this
         integer(kind=SIZE_KIND), intent(in) :: n

         newIter%currentIndex = this%currentIndex + n
         newIter%elements => this%elements

      end function v_riter_subtract

      function v_riter_add_32(this, n) result(newIter)
         type (StringVectorRIterator) :: newIter
         class (StringVectorRIterator), intent(in) :: this
         integer, intent(in) :: n

         newIter = this + int(n, kind=SIZE_KIND)

      end function v_riter_add_32

      function v_riter_subtract_32(this, n) result(newIter)
         type (StringVectorRIterator) :: newIter
         class (StringVectorRIterator), intent(in) :: this
         integer, intent(in) :: n

         newIter = this - int(n, kind=SIZE_KIND)

      end function v_riter_subtract_32

end module gFTL_StringVector

module BensTypeMod
   use gFTL_StringVector
   implicit none

   public BensType
   type BensType
      private
      type(StringVector) :: order
      contains
         procedure :: add_to_order
   end type BensType

contains

subroutine add_to_order(this,val)
   class(BensType), target, intent(Inout) :: this
   character(len=*), intent(in) :: val
   call this%order%push_back(val)
end subroutine add_to_order

end module BensTypeMod

module BensTypeVectorMod
   use BensTypeMod

      implicit none

      integer, parameter :: SIZE_KIND =                                        &
     &           max(kind(1),selected_int_kind(18))

      type Unusable
      end type Unusable

      private

      public :: BensTypeVector
      public :: BensTypeVectorIterator
      public :: BensTypeVectorRIterator
      public :: swap

      type :: BensTypeVector
         private
         type (BensType), allocatable :: elements(:)
         integer(kind=SIZE_KIND) :: vsize = 0
      contains
         procedure :: size => v_size
         procedure :: capacity => v_capacity
         procedure :: empty => v_empty

         procedure :: at_size_kind => v_at_size_kind
         generic :: at => at_size_kind

         procedure :: at_32 => v_at_32
         generic :: at => at_32

         procedure :: of => v_of
         procedure :: get_size_kind => v_get_size_kind
         generic :: get => get_size_kind

         procedure :: get_32 => v_get_32
         generic :: get => get_32

         procedure :: get_data => v_get_data

         procedure :: back => v_back
         procedure :: front => v_front

         procedure :: set_size_kind => v_set_size_kind
         generic :: set => set_size_kind

         procedure :: set_32 => v_set_32
         generic :: set => set_32

         procedure :: copyFromArray => v_copyfromarray

         generic :: assignment(=) => copyFromArray

         procedure :: push_back => v_push_back
         procedure :: pop_back => v_pop_back
         procedure :: insert_size_kind => v_insert_size_kind
         generic :: insert => insert_size_kind

         procedure :: insert_32 => v_insert_32
         generic :: insert => insert_32

         procedure :: resize_size => v_resize_size
         generic :: resize => resize_size

         procedure :: resize_32 => v_resize_32
         generic :: resize => resize_32

         procedure :: clear => v_clear
         procedure :: shrink_to_fit => v_shrink_to_fit

         procedure :: v_erase_one
         procedure :: v_erase_range
         generic :: erase => v_erase_one, v_erase_range

         procedure :: reserve_size_kind => v_reserve_size_kind
         generic :: reserve => reserve_size_kind

         procedure :: reserve_32 => v_reserve_32
         generic :: reserve => reserve_32

         procedure :: swap => v_swap
         procedure :: reset => v_reset

         procedure :: begin => v_begin
         procedure :: end => v_end

         procedure :: rbegin => v_rbegin
         procedure :: rend => v_rend

         procedure, private :: set_capacity => v_set_capacity
         procedure, private :: grow_to => v_grow_to
         procedure, private :: downsize=>v_downsize
      end type BensTypeVector

      interface BensTypeVector
         module procedure v_new_empty
      end interface BensTypeVector

      interface swap
         module procedure v_swap
      end interface swap

      type BensTypeVectorIterator
         private

         type (BensType), dimension(:), pointer :: elements
         integer(kind=SIZE_KIND) :: currentIndex = -1 ! intentionally invalid value

      contains

         procedure :: get => v_iter_get
         procedure :: next => v_iter_next
         procedure :: previous => v_iter_previous
         procedure :: v_iter_atDefault
         generic :: at => v_iter_atDefault
         procedure :: v_iter_atOffset
         generic :: at => v_iter_atOffset

         procedure :: v_iter_atOffset_32
         generic :: at => v_iter_atOffset_32

         procedure :: v_iter_equal
         procedure ::  v_not_iter_equal
         generic :: operator(==) => v_iter_equal
         generic :: operator(/=) => v_not_iter_equal

         procedure :: v_iter_less
         procedure :: v_iter_less_equal
         procedure :: v_iter_greater
         procedure :: v_iter_greater_equal
         generic :: operator(<) => v_iter_less
         generic :: operator(<=) => v_iter_less_equal
         generic :: operator(>) => v_iter_greater
         generic :: operator(>=) => v_iter_greater_equal

         procedure :: v_iter_add
         procedure :: v_iter_subtract
         generic :: operator(+) => v_iter_add
         generic :: operator(-) => v_iter_subtract

         procedure :: v_iter_add_32
         procedure :: v_iter_subtract_32
         generic :: operator(+) => v_iter_add_32
         generic :: operator(-) => v_iter_subtract_32

      end type BensTypeVectorIterator

      type BensTypeVectorRIterator
         private

         type (BensType), dimension(:), pointer :: elements
         integer(kind=SIZE_KIND) :: currentIndex = -1 ! intentionally invalid value

      contains

         procedure :: get => v_riter_get
         procedure :: next => v_riter_next
         procedure :: previous => v_riter_previous

         procedure :: v_riter_atDefault
         generic :: at => v_riter_atDefault
         procedure :: v_riter_atOffset
         generic :: at => v_riter_atOffset

         procedure :: v_riter_atOffset_32
         generic :: at => v_riter_atOffset_32

         procedure :: v_riter_equal
         procedure :: v_riter_not_equal
         generic :: operator(==) => v_riter_equal
         generic :: operator(/=) => v_riter_not_equal

         procedure :: v_riter_less
         procedure :: v_riter_less_equal
         procedure :: v_riter_greater
         procedure :: v_riter_greater_equal
         generic :: operator(<) => v_riter_less
         generic :: operator(<=) => v_riter_less_equal
         generic :: operator(>) => v_riter_greater
         generic :: operator(>=) => v_riter_greater_equal

         procedure :: v_riter_add
         procedure :: v_riter_subtract
         generic :: operator(+) => v_riter_add
         generic :: operator(-) => v_riter_subtract

         procedure :: v_riter_add_32
         procedure :: v_riter_subtract_32
         generic :: operator(+) => v_riter_add_32
         generic :: operator(-) => v_riter_subtract_32

      end type BensTypeVectorRIterator

      integer, parameter :: SUCCESS = 0
      integer, parameter :: OUT_OF_RANGE = 1
      integer, parameter :: BAD_ALLOC = 2
      integer, parameter :: ILLEGAL_INPUT = 3

      type :: KeywordEnforcer
      end type KeywordEnforcer

      contains

      function v_new_empty() result(v)
         type (BensTypeVector) :: v
         logical, parameter :: flag = .false.
         if (flag) print*,shape(v) ! avoid warning about unused return value
         return
      end function v_new_empty

      pure function v_size(this) result(res)
         class(BensTypeVector), intent(in) :: this
         integer(kind=SIZE_KIND) :: res

         res=this%vsize
         return
      end function v_size

      pure function v_capacity(this) result(capacity)
         integer(kind=SIZE_KIND) :: capacity
         class (BensTypeVector), intent(in) :: this

         if (allocated(this%elements)) then
            capacity = size(this%elements)
         else
            capacity = 0
         end if

      end function v_capacity

      pure logical function v_empty(this) result(empty)
         class(BensTypeVector), intent(in) :: this

         empty = this%vsize==0

      end function v_empty

      function v_at_size_kind(this, i, unused, rc) result(res)
         class(BensTypeVector), target, intent(in) :: this
         integer(KIND=SIZE_KIND), intent(in) :: i
         type (KeywordEnforcer), optional, intent(in) :: unused
         integer, optional, intent(out) :: rc
         type (BensType) , pointer :: res

         if (.false.) print*,shape(unused)

         if ((i<=0).or.(i>this%vsize)) then
            if (present(rc)) rc = OUT_OF_RANGE
            return
         end if

         res=>this%elements(i)
         return
      end function v_at_size_kind

      function v_at_32(this, i, unused, rc) result(res)
         class(BensTypeVector), target, intent(in) :: this
         integer, intent(in) :: i
         type (BensType) , pointer :: res
         type (KeywordEnforcer), optional, intent(in) :: unused
         integer, optional, intent(out) :: rc

         if (.false.) print*,shape(unused)

         res => this%at_size_kind(int(i,kind=SIZE_KIND),rc=rc)

      end function v_at_32

      function v_of(this, i) result(res)
         class(BensTypeVector), target, intent(in) :: this
         integer, intent(in) :: i
         type (BensType) , pointer :: res

         res=>this%elements(i)
         return
      end function v_of

      function v_get_size_kind(this, i) result(res)
         class(BensTypeVector), target, intent(in) :: this
         integer(kind=SIZE_KIND), intent(in) :: i
         type (BensType)  :: res
         integer(kind=SIZE_KIND) :: idx

         idx=merge(i, this%vsize+i, i>0)
         res=this%elements(idx)

      end function v_get_size_kind

      function v_get_32(this, i) result(res)
         class(BensTypeVector), target, intent(in) :: this
         integer, intent(in) :: i
         type (BensType)  :: res

         integer(kind=SIZE_KIND) :: idx
         integer(kind=SIZE_KIND) :: i64
         i64 = int(i,kind=SIZE_KIND)
         idx=merge(i64, this%vsize+i64, i64>0)
         res=this%elements(idx)

      end function v_get_32

      function v_get_data(this) result(res)
         class(BensTypeVector), target, intent(in) :: this
         type (BensType), dimension(:), pointer :: res

         res=>this%elements(:this%vsize)
         return
      end function v_get_data

      function v_back(this) result(res)
         class(BensTypeVector), target, intent(in) :: this
         type (BensType) , pointer :: res

         res=>this%elements(this%vsize)
         return
      end function v_back

      function v_front(this) result(res)
         class(BensTypeVector), target, intent(in) :: this
         type (BensType) , pointer :: res

         res=>this%elements(1)
         return
      end function v_front

      subroutine v_set_size_kind(this, i, value)
         class(BensTypeVector), intent(inout) :: this
         integer(kind=SIZE_KIND), intent(in) :: i
         type (BensType) , intent(in) :: value

         integer(kind=SIZE_KIND) :: idx

         idx=merge(i, this%vsize+i, i>0)

         this%elements(idx)=value
         return
      end subroutine v_set_size_kind

      subroutine v_set_32(this, i, value)
         class(BensTypeVector), intent(inout) :: this
         integer, intent(in) :: i
         type (BensType) , intent(in) :: value

         call this%set(int(i,kind=SIZE_KIND), value)

      end subroutine v_set_32

      subroutine v_reset(this)
         class(BensTypeVector), intent(inout) :: this

         if (allocated(this%elements)) then
            deallocate(this%elements)
         end if
         this%vsize=0
         return
      end subroutine v_reset

      subroutine v_copyFromArray(this, array)
         class(BensTypeVector), intent(inout) :: this
         type (BensType), target, intent(in) :: array(:)

         integer(kind=SIZE_KIND) :: n

         n = size(array)

         call this%reserve(n)
         this%elements(1:n) = array(1:n)
         this%vsize=n

         return
      end subroutine v_copyFromArray

      subroutine v_push_back(this, value, unused, rc)
         class(BensTypeVector), intent(inout) :: this
         type (BensType) , intent(in) :: value
         type (KeywordEnforcer), optional, intent(in) :: unused
         integer, optional, intent(out) :: rc

         if (.false.) print*,shape(unused)

         call this%grow_to(this%vsize+1)
         call this%resize(this%vsize+1, value, rc=rc)
         return

      end subroutine v_push_back

      subroutine v_pop_back(this)
         class(BensTypeVector), intent(inout) :: this

         call this%downsize(this%vsize-1)
         return
      end subroutine v_pop_back

      subroutine v_insert_size_kind(                                                 &
     &   this, index, value, unused, rc)
         class(BensTypeVector), target, intent(inout) :: this

         integer(kind=SIZE_KIND), intent(in) :: index

         type (BensType) , intent(in) :: value
         type (KeywordEnforcer), optional, intent(in) :: unused
         integer, optional, intent(out) :: rc

         type (BensType)  :: temp
         integer(kind=SIZE_KIND) :: i, n

         if (.false.) print*,shape(unused)

         n = this%vsize
         if (index==n+1) then
            call this%push_back(value)
            temp=value
            return
         endif
         call this%grow_to(this%vsize+1)
         temp=this%elements(n)
         call this%resize(n+1, temp, rc=rc)

         do i = n, index, -1
          this%elements(i+1)=this%elements(i)
         end do

         this%elements(index)=value

         return
      end subroutine v_insert_size_kind

      subroutine v_insert_32(this, index, value)
         class(BensTypeVector), intent(inout) :: this
         integer, intent(in) :: index
         type (BensType) , intent(in) :: value

         call this%insert(int(index,kind=SIZE_KIND), value)
      end subroutine v_insert_32

      subroutine v_resize_size(this, newsize, value, unused, rc)
         class(BensTypeVector), intent(inout) :: this
         integer(kind=SIZE_KIND), intent(in) :: newsize
         type (BensType) , optional, intent(in) :: value
         type (KeywordEnforcer), optional, intent(in) :: unused
         integer, optional, intent(out) :: rc

         integer(kind=SIZE_KIND) :: oldSize
         integer(kind=SIZE_KIND) :: i

         if (.false.) print*,shape(unused)

         if (newSize == this%vsize) return
         if (newSize < 0) then
            if (present(rc)) rc = ILLEGAL_INPUT
            return
         end if
         oldSize=this%vsize

         call this%reserve(newSize)
         this%vsize = newSize

         do i = newSize + 1, oldSize

         end do

         if (present(value) .and. (newsize>oldsize)) then
            do i = oldSize + 1, newSize
               this%elements(i)=value
            end do
         endif
         return
      end subroutine v_resize_size

      subroutine v_resize_32(this, newsize, value, unused, rc)
         class(BensTypeVector), intent(inout) :: this
         integer, intent(in) :: newsize
         type (BensType) , optional, intent(in) :: value
         type (KeywordEnforcer), optional, intent(in) :: unused
         integer, optional, intent(out) :: rc

         if (.false.) print*,shape(unused)

         call this%resize(int(newsize,kind=SIZE_KIND), value, rc=rc)

      end subroutine v_resize_32

      subroutine v_downsize(this, newsize)
         class(BensTypeVector), intent(inout) :: this
         integer(kind=SIZE_KIND), intent(in) :: newsize  ! assumes newsize<=size()
         integer(kind=SIZE_KIND) :: i

         if (newsize<this%vsize) then
           do i=newsize+1, this%vsize

           end do
           this%vsize=newsize
         endif

         return
      end subroutine v_downsize

      subroutine v_clear(this)
         class(BensTypeVector), intent(inout) :: this

         call this%downsize(0_SIZE_KIND)

         return
      end subroutine v_clear

      subroutine v_shrink_to_fit(this)
         class(BensTypeVector), intent(inout) :: this

         if (this%vsize<this%capacity()) then
           call this%set_capacity(this%vsize)
         endif
         return
      end subroutine v_shrink_to_fit

      subroutine v_erase_one(this, position)
         class(BensTypeVector), target, intent(inout) :: this
         type (BensTypeVectorIterator), intent(in)  :: position

         call this%erase(position, position+1)

         return
      end subroutine v_erase_one

      subroutine v_erase_range(this, first, last)
         class(BensTypeVector), target, intent(inout) :: this
         type (BensTypeVectorIterator), intent(in)  :: first
         type (BensTypeVectorIterator), intent(in)  :: last

         integer :: i, delta

         delta=last%currentindex-first%currentindex
         do i=last%currentIndex, this%vsize
            associate(a => this%elements(i-delta),b =>this%elements(i))
              a=b
            end associate
!!$            this%elements(i-delta) = this%elements(i)
         end do
         do i = this%vsize - delta + 1, last%currentIndex - 1

         end do
         this%vsize=this%vsize-delta

         return
      end subroutine v_erase_range

      subroutine v_reserve_size_kind(this, capacity)
         class(BensTypeVector), intent(inout) :: this
         integer(kind=SIZE_KIND), intent(in) :: capacity

         if (capacity>this%capacity()) then
           call this%set_capacity(capacity)
         endif

         return
      end subroutine v_reserve_size_kind

      subroutine v_reserve_32(this, capacity)
         class(BensTypeVector), intent(inout) :: this
         integer, intent(in) :: capacity

         call this%reserve(int(capacity,kind=SIZE_KIND))
         return
      end subroutine v_reserve_32

      subroutine v_set_capacity(this, capacity)
         class(BensTypeVector), target, intent(inout) :: this
         integer(kind=SIZE_KIND), intent(in) :: capacity  ! capacity must be >=0
         type (BensType),dimension(:),allocatable,target :: temp
         integer(kind=SIZE_KIND) :: i

         if (capacity>0) then                     ! capacity>0
           if (.not.allocated(this%elements)) then   ! not allocated
             allocate(this%elements(capacity))
           else                                      ! allocated
             allocate(temp(capacity))
             do i=1, this%vsize
               temp(i)=this%elements(i)
             end do
             deallocate(this%elements)
             call move_alloc(temp, this%elements)
           endif
         else if (allocated(this%elements)) then  ! capacity==0
            deallocate(this%elements)
         endif

         return
      end subroutine v_set_capacity

      subroutine v_grow_to(this, capacity)
         class(BensTypeVector), intent(inout) :: this
         integer(kind=SIZE_KIND), intent(in) :: capacity

         if (capacity>this%capacity()) then
           call this%set_capacity(max(2*this%vsize, capacity)) ! gives O(n) algorithm for growing vector with push.
         endif
         return
      end subroutine v_grow_to

      subroutine v_swap(this, other)
         class(BensTypeVector), target, intent(inout) :: this
         type(BensTypeVector), target, intent(inout) :: other
         type (BensType),                                                                &
     &           dimension(:), allocatable :: tmpelementsfer
         integer :: tmpsize

         call move_alloc(this%elements, tmpelementsfer)
         call move_alloc(other%elements, this%elements)
         call move_alloc(tmpelementsfer, other%elements)
         tmpsize=this%vsize
         this%vsize=other%vsize
         other%vsize=tmpsize
         return
      end subroutine v_swap

      function v_begin(this) result(iter)
         type (BensTypeVectorIterator) :: iter
         class (BensTypeVector), target, intent(in) :: this

         iter%currentIndex = 1
         if (allocated(this%elements)) then
            iter%elements => this%elements
         else
            iter%elements => null()
         end if

      end function v_begin

      function v_end(this) result(iter)
         class (BensTypeVector), target, intent(in) :: this
         type (BensTypeVectorIterator) :: iter

         iter%currentIndex = this%size() + 1 ! past the end
         if (allocated(this%elements)) then
            iter%elements => this%elements
         else
            iter%elements => null()
         end if

      end function v_end

      function v_rbegin(this) result(iter)
         type (BensTypeVectorRIterator) :: iter
         class (BensTypeVector), target, intent(in) :: this

         iter%currentIndex = this%vsize
         if (allocated(this%elements)) then
            iter%elements => this%elements
         else
            iter%elements => null()
         end if

      end function v_rbegin

      function v_rend(this) result(iter)
         class (BensTypeVector), target, intent(in) :: this
         type (BensTypeVectorRIterator) :: iter

         iter%currentIndex = 0 ! before beginning
         if (allocated(this%elements)) then
            iter%elements => this%elements
         else
            iter%elements => null()
         end if

      end function v_rend

      function v_iter_get(this) result (item)
         class (BensTypeVectorIterator), intent(in) :: this

         type (BensType) , pointer :: item
         item => this%elements(this%currentIndex)

      end function v_iter_get

      subroutine v_iter_next(this)
         class (BensTypeVectorIterator), intent(inout) :: this
         this%currentIndex = this%currentIndex + 1
      end subroutine v_iter_next

      subroutine v_iter_previous(this)
         class (BensTypeVectorIterator), intent(inout) :: this
         this%currentIndex = this%currentIndex - 1
      end subroutine v_iter_previous

      logical function v_iter_equal(this, other) result(eq)
         class (BensTypeVectorIterator), intent(in) :: this
         class (BensTypeVectorIterator), intent(in) :: other

         eq = (this%currentIndex == other%currentIndex)

      end function v_iter_equal

      logical function v_not_iter_equal(this, other) result(ne)
         class (BensTypeVectorIterator), intent(in) :: this
         class (BensTypeVectorIterator), intent(in) :: other

         ne = .not. (this == other)

      end function v_not_iter_equal

      logical function v_iter_less(this, other) result(less)
         class (BensTypeVectorIterator), intent(in) :: this
         class (BensTypeVectorIterator), intent(in) :: other
         less = (this%currentIndex < other%currentIndex)
      end function v_iter_less

      function v_iter_less_equal(this,other) result(le)
         logical :: le
         class (BensTypeVectorIterator), intent(in) :: this
         class (BensTypeVectorIterator), intent(in) :: other
         le = (this%currentIndex <= other%currentIndex)
      end function v_iter_less_equal

      logical function v_iter_greater(this, other) result(gt)
         class (BensTypeVectorIterator), intent(in) :: this
         class (BensTypeVectorIterator), intent(in) :: other
         gt = (this%currentIndex > other%currentIndex)
      end function v_iter_greater

      function v_iter_greater_equal(this,other) result(gte)
         logical :: gte
         class (BensTypeVectorIterator), intent(in) :: this
         class (BensTypeVectorIterator), intent(in) :: other
         gte = (this%currentIndex >= other%currentIndex)
      end function v_iter_greater_equal

      function v_iter_atDefault(this) result(ptr)
         type (BensType) , pointer :: ptr
         class (BensTypeVectorIterator), intent(in) :: this

         ptr => this%elements(this%currentIndex)

      end function v_iter_atDefault

      function v_iter_atOffset(this, i) result(ptr)
         type (BensType) , pointer :: ptr
         class (BensTypeVectorIterator), intent(in) :: this
         integer(kind=SIZE_KIND), intent(in) :: i

         ptr => this%elements(this%currentIndex + i)

      end function v_iter_atOffset

      function v_iter_atOffset_32(this, i) result(ptr)
         type (BensType) , pointer :: ptr
         class (BensTypeVectorIterator), intent(in) :: this
         integer, intent(in) :: i

         ptr => this%elements(this%currentIndex + i)

      end function v_iter_atOffset_32

      function v_iter_add(this, n) result(newIter)
         type (BensTypeVectorIterator) :: newIter
         class (BensTypeVectorIterator), intent(in) :: this
         integer(kind=SIZE_KIND), intent(in) :: n

         newIter%currentIndex = this%currentIndex + n
         newIter%elements => this%elements

      end function v_iter_add

      function v_iter_subtract(this, n) result(newIter)
         type (BensTypeVectorIterator) :: newIter
         class (BensTypeVectorIterator), intent(in) :: this
         integer(kind=SIZE_KIND), intent(in) :: n

         newIter%currentIndex = this%currentIndex - n
         newIter%elements => this%elements

      end function v_iter_subtract

      function v_iter_add_32(this, n) result(newIter)
         type (BensTypeVectorIterator) :: newIter
         class (BensTypeVectorIterator), intent(in) :: this
         integer, intent(in) :: n

         newIter = this + int(n,kind=SIZE_KIND)

      end function v_iter_add_32

      function v_iter_subtract_32(this, n) result(newIter)
         type (BensTypeVectorIterator) :: newIter
         class (BensTypeVectorIterator), intent(in) :: this
         integer, intent(in) :: n

         newIter = this - int(n,kind=SIZE_KIND)

      end function v_iter_subtract_32

      function v_riter_get(this) result (item)
         class (BensTypeVectorRIterator), intent(in) :: this
         type (BensType) , pointer :: item
         item => this%elements(this%currentIndex)

      end function v_riter_get

      subroutine v_riter_next(this)
         class (BensTypeVectorRIterator), intent(inout) :: this
         this%currentIndex = this%currentIndex - 1
      end subroutine v_riter_next

      subroutine v_riter_previous(this)
         class (BensTypeVectorRIterator), intent(inout) :: this
         this%currentIndex = this%currentIndex + 1
      end subroutine v_riter_previous

      logical function v_riter_equal(this, other) result(eq)
         class (BensTypeVectorRIterator), intent(in) :: this
         class (BensTypeVectorRIterator), intent(in) :: other

         eq = (this%currentIndex == other%currentIndex)

      end function v_riter_equal

      logical function v_riter_not_equal(this,other)result(neq)
         class (BensTypeVectorRIterator), intent(in) :: this
         class (BensTypeVectorRIterator), intent(in) :: other

         neq = .not. (this == other)

      end function v_riter_not_equal

      function v_riter_less(this, other) result(lt)
         logical :: lt
         class (BensTypeVectorRIterator), intent(in) :: this
         class (BensTypeVectorRIterator), intent(in) :: other
         lt = (this%currentIndex > other%currentIndex)
      end function v_riter_less

      function v_riter_less_equal(this, other) result (lte)
         logical :: lte
         class (BensTypeVectorRIterator), intent(in) :: this
         class (BensTypeVectorRIterator), intent(in) :: other
         lte = (this%currentIndex >= other%currentIndex)
      end function v_riter_less_equal

      function v_riter_greater(this, other) result(gt)
         logical :: gt
         class (BensTypeVectorRIterator), intent(in) :: this
         class (BensTypeVectorRIterator), intent(in) :: other
         gt = (this%currentIndex < other%currentIndex)
      end function v_riter_greater

      function v_riter_greater_equal(this, other) result(gte)
         logical :: gte
         class (BensTypeVectorRIterator), intent(in) :: this
         class (BensTypeVectorRIterator), intent(in) :: other
         gte = (this%currentIndex <= other%currentIndex)
      end function v_riter_greater_equal

      function v_riter_atDefault(this) result(ptr)
         type (BensType) , pointer :: ptr
         class (BensTypeVectorRIterator), intent(in) :: this

         ptr => this%elements(this%currentIndex)

      end function v_riter_atDefault

      function v_riter_atOffset(this, i) result(ptr)
         type (BensType) , pointer :: ptr
         class (BensTypeVectorRIterator), intent(in) :: this
         integer(kind=SIZE_KIND), intent(in) :: i

         ptr => this%elements(this%currentIndex - i)

      end function v_riter_atOffset

      function v_riter_atOffset_32(this, i) result(ptr)
         type (BensType) , pointer :: ptr
         class (BensTypeVectorRIterator), intent(in) :: this
         integer, intent(in) :: i

         ptr => this%elements(this%currentIndex - i)

      end function v_riter_atOffset_32

      function v_riter_add(this, n) result(newIter)
         type (BensTypeVectorRIterator) :: newIter
         class (BensTypeVectorRIterator), intent(in) :: this
         integer(kind=SIZE_KIND), intent(in) :: n

         newIter%currentIndex = this%currentIndex - n
         newIter%elements => this%elements

      end function v_riter_add

      function v_riter_subtract(this, n) result(newIter)
         type (BensTypeVectorRIterator) :: newIter
         class (BensTypeVectorRIterator), intent(in) :: this
         integer(kind=SIZE_KIND), intent(in) :: n

         newIter%currentIndex = this%currentIndex + n
         newIter%elements => this%elements

      end function v_riter_subtract

      function v_riter_add_32(this, n) result(newIter)
         type (BensTypeVectorRIterator) :: newIter
         class (BensTypeVectorRIterator), intent(in) :: this
         integer, intent(in) :: n

         newIter = this + int(n, kind=SIZE_KIND)

      end function v_riter_add_32

      function v_riter_subtract_32(this, n) result(newIter)
         type (BensTypeVectorRIterator) :: newIter
         class (BensTypeVectorRIterator), intent(in) :: this
         integer, intent(in) :: n

         newIter = this - int(n, kind=SIZE_KIND)

      end function v_riter_subtract_32

end module BensTypeVectorMod

program test_erase

use BensTypeMod
use BensTypeVectorMod
implicit none

integer, parameter :: max_num=2
type (BensTypeVector), target :: bvec

call main()

contains

   subroutine main()

      write(*,*)'adding'
      call new_entry2("bob","tim")
      write(*,*)'adding'
      call new_entry3("stacy","tonia","crash")
      write(*,*)'adding'
      call new_entry2("paul1","paul2")

   end subroutine main

   subroutine new_entry2(a,b)
      character(len=*), intent(in) :: a
      character(len=*), intent(in) :: b
      type(BensType), pointer :: bp

      if (bvec%size() >= max_num) then
         write(*,*)'erasing'
         call bvec%erase(bvec%begin())
      end if

      allocate(bp)
      call bp%add_to_order(a)
      call bp%add_to_order(b)
      call bvec%push_back(bp)
      deallocate(bp)
   end subroutine new_entry2

   subroutine new_entry3(a,b,c)
      character(len=*), intent(in) :: a
      character(len=*), intent(in) :: b
      character(len=*), intent(in) :: c
      type(BensType), pointer :: bp
      if (bvec%size() >= max_num) then
         write(*,*)'erasing'
         bp => bvec%front()
         call bvec%erase(bvec%begin())
         nullify(bp)
      end if

      allocate(bp)
      call bp%add_to_order(a)
      call bp%add_to_order(b)
      call bp%add_to_order(c)
      call bvec%push_back(bp)
      deallocate(bp)
   end subroutine new_entry3

end program test_erase 
