vec_int32_grow Subroutine

private pure subroutine vec_int32_grow(self, needed, err)

Ensure capacity for at least needed elements, preserving the live ones. Capacity starts at PIC_VECTOR_MIN_CAPACITY and doubles, which keeps a run of push_back calls amortised O(1).

Arguments

Type IntentOptional Attributes Name
class(vector_int32_t), intent(inout) :: self
integer(kind=default_int), intent(in) :: needed
type(error_t), intent(inout), optional :: err

Calls

proc~~vec_int32_grow~~CallsGraph proc~vec_int32_grow vec_int32_grow proc~error_raise error_raise proc~vec_int32_grow->proc~error_raise proc~vec_int32_capacity vector_int32_t%vec_int32_capacity proc~vec_int32_grow->proc~vec_int32_capacity proc~error_set error_t%error_set proc~error_raise->proc~error_set

Called by

proc~~vec_int32_grow~~CalledByGraph proc~vec_int32_grow vec_int32_grow proc~vec_int32_append vector_int32_t%vec_int32_append proc~vec_int32_append->proc~vec_int32_grow proc~vec_int32_push_back vector_int32_t%vec_int32_push_back proc~vec_int32_push_back->proc~vec_int32_grow proc~vec_int32_reserve vector_int32_t%vec_int32_reserve proc~vec_int32_reserve->proc~vec_int32_grow proc~vec_int32_resize vector_int32_t%vec_int32_resize proc~vec_int32_resize->proc~vec_int32_grow

Variables

Type Visibility Attributes Name Initial
integer(kind=int32), private, allocatable :: bigger(:)
integer(kind=default_int), private :: new_capacity
integer, private :: stat

Source Code

   pure subroutine vec_int32_grow(self, needed, err)
      !! Ensure capacity for at least `needed` elements, preserving the live
      !! ones. Capacity starts at PIC_VECTOR_MIN_CAPACITY and doubles, which
      !! keeps a run of `push_back` calls amortised O(1).
      class(vector_int32_t), intent(inout) :: self
      integer(default_int), intent(in) :: needed
      type(error_t), intent(inout), optional :: err

      integer(int32), allocatable :: bigger(:)
      integer(default_int) :: new_capacity
      integer :: stat

      if (needed <= vec_int32_capacity(self)) return

      ! `needed` is negative only if a caller's arithmetic wrapped on the way
      ! in. It cannot be compared against PIC_VECTOR_MAX_CAPACITY, which is
      ! `huge(0_default_int)` and so can never be exceeded by a value of that
      ! kind -- a guard written that way is dead code. The callers below check
      ! their headroom before adding; this catches anything that slips past.
      if (needed < 0_default_int) then
         call error_raise(err, ERROR_ALLOC, &
                          "vector_int32_t: requested capacity overflowed.")
         return
      end if

      new_capacity = max(vec_int32_capacity(self), PIC_VECTOR_MIN_CAPACITY)
      do while (new_capacity < needed)
         ! Doubling is done only when it cannot overflow default_int; past that
         ! point the clamp is the only remaining step, and `needed` is already
         ! known to fit.
         if (new_capacity > PIC_VECTOR_MAX_CAPACITY/2) then
            new_capacity = PIC_VECTOR_MAX_CAPACITY
            exit
         end if
         new_capacity = 2*new_capacity
      end do

      allocate (bigger(new_capacity), stat=stat)
      ! `allocated` rather than `stat`: nvfortran does not set stat reliably
      ! for every element type, while `allocated` always reports the truth.
      if (.not. allocated(bigger)) then
         call error_raise(err, ERROR_ALLOC, "vector_int32_t: allocation of backing storage failed.")
         return
      end if

      if (self%n_items > 0) bigger(1:self%n_items) = self%items(1:self%n_items)
      call move_alloc(bigger, self%items)
   end subroutine vec_int32_grow