Ensures that an array is appropriately large.
Type | Intent | Optional | Attributes | Name | ||
---|---|---|---|---|---|---|
integer(kind=int_8), | DIMENSION(:), POINTER, CONTIGUOUS | :: | array |
array to verify and possibly resize |
||
integer(kind=int_8), | optional, | DIMENSION(:), POINTER | :: | array_resize | ||
integer, | intent(in), | optional | :: | lb |
desired array lower bound |
|
integer, | intent(in) | :: | ub |
desired array upper bound |
||
real(kind=dp), | intent(in), | optional | :: | factor |
factor by which to exaggerate enlargements |
|
logical, | intent(in), | optional | :: | nocopy |
copy array on enlargement; default is to copy zero new allocations; default is to write nothing |
|
type(dbcsr_memtype_type), | intent(in), | optional | :: | memory_type |
use special memory |
|
logical, | intent(in), | optional | :: | zero_pad |
copy array on enlargement; default is to copy zero new allocations; default is to write nothing |
SUBROUTINE ensure_array_size_l (array, array_resize, lb, ub, factor, & nocopy, memory_type, zero_pad) !! Ensures that an array is appropriately large. INTEGER(kind=int_8), DIMENSION(:), POINTER, CONTIGUOUS :: array !! array to verify and possibly resize INTEGER(kind=int_8), DIMENSION(:), POINTER, OPTIONAL :: array_resize INTEGER, INTENT(IN), OPTIONAL :: lb !! desired array lower bound INTEGER, INTENT(IN) :: ub !! desired array upper bound REAL(KIND=dp), INTENT(IN), OPTIONAL :: factor !! factor by which to exaggerate enlargements LOGICAL, INTENT(IN), OPTIONAL :: nocopy, zero_pad !! copy array on enlargement; default is to copy !! zero new allocations; default is to write nothing TYPE(dbcsr_memtype_type), INTENT(IN), OPTIONAL :: memory_type !! use special memory CHARACTER(len=*), PARAMETER :: routineN = 'ensure_array_size_l', & routineP = moduleN//':'//routineN INTEGER :: lb_new, lb_orig, & ub_new, ub_orig, old_size, & size_increase TYPE(dbcsr_memtype_type) :: mem_type LOGICAL :: dbg, docopy, & pad INTEGER(kind=int_8), DIMENSION(:), POINTER, CONTIGUOUS :: newarray ! --------------------------------------------------------------------------- !CALL timeset(routineN, error_handler) dbg = .FALSE. IF (PRESENT(array_resize)) NULLIFY (array_resize) IF (PRESENT(nocopy)) THEN docopy = .NOT. nocopy ELSE docopy = .TRUE. END IF IF (PRESENT(memory_type)) THEN mem_type = memory_type ELSE mem_type = dbcsr_memtype_default END IF lb_new = 1 IF (PRESENT(lb)) lb_new = lb pad = .FALSE. IF (PRESENT(zero_pad)) pad = zero_pad ! Creates a new array if it doesn't yet exist. IF (.NOT. ASSOCIATED(array)) THEN IF (lb_new /= 1) & DBCSR_ABORT("Arrays must start at 1") CALL mem_alloc_l (array, ub, mem_type=mem_type) IF (pad .AND. ub .GT. 0) CALL mem_zero_l (array, ub) !CALL timestop(error_handler) RETURN END IF lb_orig = LBOUND(array, 1) ub_orig = UBOUND(array, 1) old_size = ub_orig - lb_orig + 1 ! The existing array is big enough. IF (lb_orig .LE. lb_new .AND. ub_orig .GE. ub) THEN !CALL timestop(error_handler) RETURN END IF ! A reallocation must be performed IF (dbg) WRITE (*, *) routineP//' Current bounds are', lb_orig, ':', ub_orig, & '; special?' !,mem_type !CALL timeset(routineN,timing_handle) IF (lb_orig .GT. lb_new) THEN IF (PRESENT(factor)) THEN size_increase = lb_orig - lb_new size_increase = MAX(NINT(size_increase*factor), & NINT(old_size*(factor - 1)), 0) lb_new = MIN(lb_orig, lb_new - size_increase) ELSE lb_new = lb_orig END IF END IF IF (ub_orig .LT. ub) THEN IF (PRESENT(factor)) THEN size_increase = ub - ub_orig size_increase = MAX(NINT(size_increase*factor), & NINT(old_size*(factor - 1)), 0) ub_new = MAX(ub_orig, ub + size_increase) ELSE ub_new = ub END IF ELSE ub_new = ub END IF IF (dbg) WRITE (*, *) routineP//' Resizing to bounds', lb_new, ':', ub_new ! ! Deallocates the old array if it's not needed to copy the old data. IF (.NOT. docopy) THEN IF (PRESENT(array_resize)) THEN array_resize => array NULLIFY (array) ELSE CALL mem_dealloc_l (array, mem_type=mem_type) END IF END IF ! ! Allocates the new array IF (lb_new /= 1) & DBCSR_ABORT("Arrays must start at 1") CALL mem_alloc_l (newarray, ub_new - lb_new + 1, mem_type) ! ! Now copy and/or zero pad. IF (docopy) THEN IF (dbg .AND. (lb_new .GT. lb_orig .OR. ub_new .LT. ub_orig)) & DBCSR_ABORT("Old extent exceeds the new one.") IF (ub_orig - lb_orig + 1 .gt. 0) THEN !newarray(lb_orig:ub_orig) = array(lb_orig:ub_orig) CALL mem_copy_l (newarray(lb_orig:ub_orig), & array(lb_orig:ub_orig), ub_orig - lb_orig + 1) END IF IF (pad) THEN !newarray(lb_new:lb_orig-1) = 0 CALL mem_zero_l (newarray(lb_new:lb_orig - 1), (lb_orig - 1) - lb_new + 1) !newarray(ub_orig+1:ub_new) = 0 CALL mem_zero_l (newarray(ub_orig + 1:ub_new), ub_new - (ub_orig + 1) + 1) END IF IF (PRESENT(array_resize)) THEN array_resize => array NULLIFY (array) ELSE CALL mem_dealloc_l (array, mem_type=mem_type) END IF ELSEIF (pad) THEN !newarray(:) = 0 CALL mem_zero_l (newarray, SIZE(newarray)) END IF array => newarray IF (dbg) WRITE (*, *) routineP//' New array size', SIZE(array) !CALL timestop(error_handler) END SUBROUTINE ensure_array_size_l