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).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(vector_dp_t), | intent(inout) | :: | self | |||
| integer(kind=default_int), | intent(in) | :: | needed | |||
| type(error_t), | intent(inout), | optional | :: | err |
| Type | Visibility | Attributes | Name | Initial | |||
|---|---|---|---|---|---|---|---|
| real(kind=dp), | private, | allocatable | :: | bigger(:) | |||
| integer(kind=default_int), | private | :: | new_capacity | ||||
| integer, | private | :: | stat |
pure subroutine vec_dp_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_dp_t), intent(inout) :: self integer(default_int), intent(in) :: needed type(error_t), intent(inout), optional :: err real(dp), allocatable :: bigger(:) integer(default_int) :: new_capacity integer :: stat if (needed <= vec_dp_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_dp_t: requested capacity overflowed.") return end if new_capacity = max(vec_dp_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_dp_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_dp_grow