merge_index_arrays Subroutine

public subroutine merge_index_arrays(new_row_i, new_col_i, new_blk_p, new_size, old_row_i, old_col_i, old_blk_p, old_size, add_ip, add_size, new_blk_d, old_blk_d, added_size_offset, added_sizes, added_size, added_nblks)

Merges two indices

Added sizes added_size_offset and added_sizes can be optionally specified. This is meant for cases where the added blocks may be duplicates of existing blocks. In this way it is possible to recalculate new block pointers to avoid wasted space.

Note

Used in local multiply Assumes they are both pre-sorted

Arguments

Type IntentOptional Attributes Name
integer, intent(out), DIMENSION(new_size) :: new_row_i

merged result merged result merged result

integer, intent(out), DIMENSION(new_size) :: new_col_i

merged result merged result merged result

integer, intent(out), DIMENSION(new_size) :: new_blk_p

merged result merged result merged result

integer, intent(in) :: new_size

size of merged index

integer, intent(in), DIMENSION(old_size) :: old_row_i

current index current index current index

integer, intent(in), DIMENSION(old_size) :: old_col_i

current index current index current index

integer, intent(in), DIMENSION(old_size) :: old_blk_p

current index current index current index

integer, intent(in) :: old_size

size of current index

integer, intent(in), DIMENSION(3, add_size) :: add_ip

index to add into the current index

integer, intent(in) :: add_size

size of index to add into the current index

integer, intent(out), optional, DIMENSION(new_size) :: new_blk_d
integer, intent(in), optional, DIMENSION(old_size) :: old_blk_d
integer, intent(in), optional :: added_size_offset

specify base of added sizes

integer, intent(in), optional, DIMENSION(:) :: added_sizes

specify sizes of added blocks

integer, intent(out), optional :: added_size

counts number of sizes of added blocks actual number of new elements

integer, intent(out), optional :: added_nblks

counts number of sizes of added blocks actual number of new elements


Source Code

   SUBROUTINE merge_index_arrays(new_row_i, new_col_i, new_blk_p, new_size, &
                                 old_row_i, old_col_i, old_blk_p, old_size, &
                                 add_ip, add_size, new_blk_d, old_blk_d, &
                                 added_size_offset, added_sizes, added_size, added_nblks)
      !! Merges two indices
      !!
      !! Added sizes
      !! added_size_offset and added_sizes can be optionally
      !! specified. This is meant for cases where the added blocks may
      !! be duplicates of existing blocks. In this way it is possible
      !! to recalculate new block pointers to avoid wasted space.
      !! @note Used in local multiply
      !! Assumes they are both pre-sorted

      INTEGER, INTENT(IN)                                :: new_size
         !! size of merged index
      INTEGER, DIMENSION(new_size), INTENT(OUT)          :: new_blk_p, new_col_i, new_row_i
         !! merged result
         !! merged result
         !! merged result
      INTEGER, INTENT(IN)                                :: old_size
         !! size of current index
      INTEGER, DIMENSION(old_size), INTENT(IN)           :: old_blk_p, old_col_i, old_row_i
         !! current index
         !! current index
         !! current index
      INTEGER, INTENT(IN)                                :: add_size
         !! size of index to add into the current index
      INTEGER, DIMENSION(3, add_size), INTENT(IN)        :: add_ip
         !! index to add into the current index
      INTEGER, DIMENSION(new_size), INTENT(OUT), &
         OPTIONAL                                        :: new_blk_d
      INTEGER, DIMENSION(old_size), INTENT(IN), OPTIONAL :: old_blk_d
      INTEGER, INTENT(IN), OPTIONAL                      :: added_size_offset
         !! specify base of added sizes
      INTEGER, DIMENSION(:), INTENT(IN), OPTIONAL        :: added_sizes
         !! specify sizes of added blocks
      INTEGER, INTENT(OUT), OPTIONAL                     :: added_size, added_nblks
         !! counts number of sizes of added blocks
         !! actual number of new elements

      INTEGER                                            :: add_blk, bp, i, merge_from_whom, &
                                                            new_blk, old_blk
      LOGICAL                                            :: multidata

!   ---------------------------------------------------------------------------

      bp = 0
      multidata = PRESENT(old_blk_d) .AND. PRESENT(new_blk_d)
      IF (old_size + add_size .NE. new_size) &
         DBCSR_WARN("Mismatch of new and old size")
      IF (PRESENT(added_size_offset) .NEQV. PRESENT(added_sizes)) &
         DBCSR_ABORT("Must specify a set of arguments")
      IF (PRESENT(added_sizes) .NEQV. PRESENT(added_size)) &
         DBCSR_ABORT("Must specify a set of arguments")
      IF (debug_mod) THEN
         WRITE (*, *) " Old array", old_size
         DO i = 1, old_size
            WRITE (*, '(I7,2X,I7,2X,I7)') old_row_i(i), old_col_i(i), old_blk_p(i)
         END DO
         WRITE (*, *) " Add array", add_size
         DO i = 1, add_size
            WRITE (*, '(I7,2X,I7,2X,I7)') add_ip(1:3, i)
         END DO
      END IF
      IF (PRESENT(added_nblks)) added_nblks = 0
      IF (PRESENT(added_size)) THEN
         added_size = 0
         bp = added_size_offset
      END IF
      IF (add_size .GT. 0) THEN
         old_blk = 1
         add_blk = 1
         new_blk = 1
         IF (old_size .EQ. 0) THEN
            new_row_i(1:add_size) = add_ip(1, 1:add_size)
            new_col_i(1:add_size) = add_ip(2, 1:add_size)
            new_blk_p(1:add_size) = add_ip(3, 1:add_size)
            !IF (multidata) new_blk_d(1:add_size) = add_ip(4, 1:add_size)
            IF (PRESENT(added_nblks)) added_nblks = add_size
            IF (PRESENT(added_size)) added_size = SUM(added_sizes)
         ELSE
            DO WHILE (new_blk .LE. new_size)
               merge_from_whom = 0
               IF (old_blk .LE. old_size .AND. add_blk .LE. add_size) THEN
                  IF (add_ip(1, add_blk) .EQ. old_row_i(old_blk) &
                      .AND. add_ip(2, add_blk) .EQ. old_col_i(old_blk)) THEN
                     IF (debug_mod) THEN
                        WRITE (*, *) "Duplicate block! addblk", &
                           add_blk, "oldblk", old_blk
                     END IF
                  END IF
                  ! Rows come first
                  IF (add_ip(1, add_blk) .LT. old_row_i(old_blk)) THEN
                     merge_from_whom = 2
                  ELSEIF (add_ip(1, add_blk) .GT. old_row_i(old_blk)) THEN
                     merge_from_whom = 1
                  ELSE ! Same rows, so now come the columns
                     IF (add_ip(2, add_blk) .LT. old_col_i(old_blk)) THEN
                        ! Merges from the add array
                        merge_from_whom = 2
                     ELSEIF (add_ip(2, add_blk) .GT. old_col_i(old_blk)) THEN
                        ! Merges from the old array
                        merge_from_whom = 1
                     ELSE
                        ! Merge from old array and skip one in the new array
                        IF (debug_mod) THEN
                           WRITE (*, *) "Duplicate, keeping old", &
                              add_ip(1, add_blk), add_ip(2, add_blk)
                        END IF
                        merge_from_whom = 1
                        add_blk = add_blk + 1
                     END IF
                  END IF
               ELSE
                  IF (add_blk .LE. add_size) THEN
                     ! Merges from the add array
                     merge_from_whom = 2
                  ELSEIF (old_blk .LE. old_size) THEN
                     ! Merges from the old array
                     merge_from_whom = 1
                  ELSE
                     ! Hmmm, nothing to merge...
                     merge_from_whom = 0
                     !WRITE(*,*)"Ran out of data to merge"
                  END IF
               END IF
               SELECT CASE (merge_from_whom)
               CASE (2)
                  ! Merges from the add array
                  new_row_i(new_blk) = add_ip(1, add_blk)
                  new_col_i(new_blk) = add_ip(2, add_blk)
                  new_blk_p(new_blk) = add_ip(3, add_blk)
                  !IF (multidata) new_blk_d(new_blk) = add_ip(4, add_blk)
                  IF (PRESENT(added_nblks)) added_nblks = added_nblks + 1
                  IF (PRESENT(added_sizes)) THEN
                     new_blk_p(new_blk) = bp
                     bp = bp + added_sizes(add_blk)
                     added_size = added_size + added_sizes(add_blk)
                  END IF
                  add_blk = add_blk + 1
               CASE (1)
                  ! Merges from the old array
                  new_row_i(new_blk) = old_row_i(old_blk)
                  new_col_i(new_blk) = old_col_i(old_blk)
                  new_blk_p(new_blk) = old_blk_p(old_blk)
                  IF (multidata) new_blk_p(new_blk) = old_blk_d(old_blk)
                  old_blk = old_blk + 1
               CASE DEFAULT
                  !WRITE(*,*)"Nothing to merge"
               END SELECT
               new_blk = new_blk + 1
            END DO
         END IF
      ELSE
         new_row_i(1:old_size) = old_row_i(1:old_size)
         new_col_i(1:old_size) = old_col_i(1:old_size)
         new_blk_p(1:old_size) = old_blk_p(1:old_size)
         IF (multidata) new_blk_d(1:old_size) = old_blk_d(1:old_size)
      END IF
      IF (debug_mod) THEN
         WRITE (*, *) " New array"
         DO i = 1, new_size
            WRITE (*, '(4(2X,I7))') new_row_i(i), new_col_i(i), new_blk_p(i)
         END DO
      END IF
   END SUBROUTINE merge_index_arrays