LCOV - code coverage report
Current view: top level - src/78_effpot - m_dynarray.F90 (source / functions) Coverage Total Hit
Test: coverage.info Lines: 51.1 % 186 95
Test Date: 2026-09-21 13:49:52 Functions: 37.9 % 29 11

            Line data    Source code
       1              : !!****m* ABINIT/m_dynarray
       2              : !!
       3              : !! NAME
       4              : !! m_dynarray
       5              : !!
       6              : !! FUNCTION
       7              : !! Module for int and real(dp) array which allocate memory dynamically
       8              : !! real_array_type for real(dp) and int_array_type for integer.
       9              : !! they have push (but no pop) and finalize methods.
      10              : !! TODO hexu: Is this already implemented somewhere in abinit.
      11              : !! If not, should this file be moved to the place to make it more general usable?
      12              : !!
      13              : !! MG: Yes, this module should be moved to a lower level directory so that one can reuse it in other
      14              : !! parts of the code.
      15              : !!
      16              : !!
      17              : !! COPYRIGHT
      18              : !! Copyright (C) 2010-2026 ABINIT group (hexu)
      19              : !! This file is distributed under the terms of the
      20              : !! GNU General Public Licence, see ~abinit/COPYING
      21              : !! or http://www.gnu.org/copyleft/gpl.txt .
      22              : !! For the initials of contributors, see ~abinit/doc/developers/contributors.txt .
      23              : !!
      24              : !! SOURCE
      25              : 
      26              : 
      27              : #if defined HAVE_CONFIG_H
      28              : #include "config.h"
      29              : #endif
      30              : #include "abi_common.h"
      31              : 
      32              : module m_dynamic_array
      33              :   use defs_basis
      34              :   use m_abicore
      35              :   use m_errors
      36              :   use m_mathfuncs, only: array_morethan, binsearch_left_integerlist,binsearch_left_integer
      37              :   use m_mergesort, only: MergeSort, MergeSort2D
      38              :   use m_xmpi, only: xmpi_sum, xmpi_allgather, xmpi_allgatherv
      39              :   implicit none
      40              :   private
      41              : !!***
      42              : 
      43              : !!****t* m_dynarray/real_array_type
      44              : !! NAME
      45              : !! real_array_type
      46              : !!
      47              : !! FUNCTION
      48              : !! datatype of real(dp) array which can be dynamically allocated
      49              : !!
      50              : !! SOURCE
      51              :   type, public:: real_array_type
      52              :     integer:: size=0, capacity=0
      53              :     real(dp), allocatable :: data(:)
      54              :   CONTAINS
      55              :     procedure :: push => real_array_type_push
      56              :     procedure :: sort => real_array_type_sort
      57              :     procedure :: from_static => real_array_type_from_static
      58              :     procedure :: allgatherv => real_array_type_allgatherv
      59              :     procedure :: finalize => real_array_type_finalize
      60              :   end type real_array_type
      61              : 
      62              : 
      63              : !!***
      64              : 
      65              : !!****t* m_dynarray/int_array_type
      66              : !! NAME
      67              : !! int_array_type
      68              : !!
      69              : !! FUNCTION
      70              : !! datatype of real(dp) array which can be dynamically allocated
      71              : !!
      72              : !! SOURCE
      73              :   type , public::int_array_type
      74              :     integer:: size=0, capacity=0
      75              :     integer, allocatable :: data(:)
      76              :   CONTAINS
      77              :     procedure :: push => int_array_type_push
      78              :     procedure :: concate => int_array_type_concate
      79              :     procedure :: finalize => int_array_type_finalize
      80              :     procedure :: sort => int_array_type_sort
      81              :     procedure :: tostatic => int_array_type_tostatic
      82              :     procedure :: allgatherv => int_array_type_allgatherv
      83              :   end type int_array_type
      84              : !!***
      85              : 
      86              :   !!****t* defs_abitypes/int2d_array_type
      87              :   !! NAME
      88              :   !! int2d_array_type
      89              :   !!
      90              :   !! FUNCTION
      91              :   !! datatype of integer array which the dim=2 can be dynamically allocated
      92              :   !!
      93              :   !! SOURCE
      94              :   type , public::int2d_array_type
      95              :      integer:: size=0, capacity=0, size1=-1
      96              :      logical :: sorted=.False.
      97              :      integer, allocatable :: data(:,:)
      98              :    CONTAINS
      99              :      procedure :: push => int2d_array_type_push
     100              :      procedure :: concate => int2d_array_type_concate
     101              :      procedure :: tostatic => int2d_array_type_tostatic
     102              :      procedure :: push_unique => int2d_array_type_push_unique
     103              :      procedure :: sort => int2d_array_type_sort
     104              :      procedure :: binsearch =>int2d_array_type_binsearch
     105              :      procedure :: finalize => int2d_array_type_finalize
     106              :   end type int2d_array_type
     107              :   !!***
     108              : 
     109              :   !public :: mpi_gather_int_array
     110              :   public::  dynamic_array_unittest
     111              : CONTAINS
     112              : 
     113              : !  subroutine merge_int_array(x1, x2, y)
     114              : !    class(int_array_type), intent(in) :: x
     115              : !    class(int_array_type),  :: y
     116              : 
     117              : !  end subroutine gather_int_array
     118              : 
     119              :   !subroutine mpi_gather_int_array(a, comm, y, ny)
     120              :   !  class(int_array_type) :: a
     121              :   !  integer :: comm
     122              :   !  integer, allocatable, intent(out) :: y(:, :)
     123              :   !  integer, intent(out) :: ny
     124              :   !end subroutine mpi_gather_int_array
     125              : 
     126              : 
     127              : 
     128              : 
     129              : !****f* m_dynarray/real_array_type_push
     130              : !!
     131              : !! NAME
     132              : !! real_array_type_push
     133              : !!
     134              : !! FUNCTION
     135              : !! push data to a real_array_type
     136              : !!
     137              : !! INPUTS
     138              : !! self = real_array_type object
     139              : !! val= data to be pushed
     140              : !! OUTPUT
     141              : !! real_array<type(real_array_type)()> = real_array_type data
     142              : !! SOURCE
     143      2553449 : subroutine real_array_type_push(self, val)
     144              : 
     145              :     class(real_array_type), intent(inout):: self
     146              :     real(dp) :: val
     147      2553449 :     real(dp), allocatable :: temp(:)
     148      2553449 :     self%size=self%size+1
     149      2553449 :     if(self%size==1) then
     150           25 :       self%capacity=8
     151           25 :       ABI_MALLOC(self%data, (self%capacity))
     152      2553424 :     else if ( self%size>self%capacity ) then
     153          603 :       self%capacity = self%size + self%size / 4 + 8
     154         1809 :       ABI_MALLOC(temp, (self%capacity))
     155     12015622 :       temp(:self%size-1) = self%data
     156          603 :       ABI_MOVE_ALLOC(temp, self%data)
     157              :     end if
     158      2553449 :     self%data(self%size)=val
     159              : 
     160      2553449 : end subroutine real_array_type_push
     161              : !!***
     162              : 
     163              : subroutine int_array_type_from_static(self, A)
     164              :   class(int_array_type), intent(inout):: self
     165              :   integer, intent(in) :: A(:)
     166              :   integer :: n
     167              :   n=size(A)
     168              :   self%size=n
     169              :   self%capacity=n
     170              :   ABI_MALLOC(self%data, (n))
     171              :   self%data(:) = A
     172              : end subroutine int_array_type_from_static
     173              : 
     174            0 : subroutine real_array_type_from_static(self, A)
     175              :   class(real_array_type), intent(inout):: self
     176              :   real(dp), intent(in) :: A(:)
     177              :   integer :: n
     178            0 :   n=size(A)
     179            0 :   self%size=n
     180            0 :   self%capacity=n
     181            0 :   ABI_MALLOC(self%data, (n))
     182            0 :   self%data(:) = A
     183            0 : end subroutine real_array_type_from_static
     184              : 
     185            0 : subroutine real_array_type_sort(self, order)
     186              :   class(real_array_type), intent(inout):: self
     187            0 :   real(dp):: work((self%size+1)/2)
     188              :   integer, optional, intent(inout):: order(self%size)
     189            0 :   integer :: work_order((self%size+1)/2)
     190            0 :   call MergeSort(self%data(:self%size), work, order, work_order)
     191            0 : end subroutine real_array_type_sort
     192              : 
     193            0 : subroutine real_array_type_allgatherv(self,buff, comm, nproc)
     194              :   class(real_array_type), intent(inout):: self
     195              :   integer, intent(in) :: comm, nproc
     196              :   real(dp), allocatable, intent(out) :: buff(:)
     197              :   real(dp), allocatable :: tmp(:)
     198            0 :   integer :: disps(nproc), sizes(nproc)
     199              :   integer :: totsize, ierr, i
     200            0 :   totsize=self%size
     201            0 :   call xmpi_sum(totsize, comm, ierr)
     202            0 :   ABI_MALLOC(buff, (totsize))
     203            0 :   call xmpi_allgather(self%size, sizes, comm, ierr)
     204            0 :   disps(1)=0
     205            0 :   do i=2, nproc
     206            0 :     disps(i)=disps(i-1)+sizes(i-1)
     207              :   end do
     208            0 :   ABI_MALLOC(tmp, (self%size))
     209            0 :   if(self%size>0) then
     210            0 :     tmp(:)=self%data(:self%size)
     211              :   end if
     212            0 :   call xmpi_allgatherv(tmp, self%size, buff, sizes, disps, comm, ierr  )
     213            0 :   ABI_FREE(tmp)
     214            0 : end subroutine real_array_type_allgatherv
     215              : 
     216              : 
     217              : 
     218              : !****f* m_disarray/real_array_type_finalize
     219              : !!
     220              : !! NAME
     221              : !! real_array_type_finalize
     222              : !!
     223              : !! FUNCTION
     224              : !! destroy real_array_type
     225              : !!
     226              : !! INPUTS
     227              : !! self= real_array_type object
     228              : !! OUTPUT
     229              : !! real_array<type(real_array_type)()> = real_array_type data
     230              : !! SOURCE
     231           38 : subroutine real_array_type_finalize(self)
     232              : 
     233              :   class(real_array_type), intent(inout):: self
     234           38 :   ABI_SFREE(self%data)
     235           38 :   self%size=0
     236           38 :   self%capacity=0
     237              : 
     238           38 : end subroutine real_array_type_finalize
     239              : !!***
     240              : 
     241              : !****f* m_dynarray/int_array_type_push
     242              : !!
     243              : !! NAME
     244              : !! int_array_type_push
     245              : !!
     246              : !! FUNCTION
     247              : !! push data to a int_array_type
     248              : !!
     249              : !! INPUTS
     250              : !! self = int_array_type object
     251              : !! val= data to be pushed
     252              : !! OUTPUT
     253              : !! int_array<type(real_array_type)()> = int_array_type data
     254              : !! SOURCE
     255        28015 : subroutine int_array_type_push(self, val)
     256              : 
     257              :     class(int_array_type), intent(inout):: self
     258              :     integer :: val
     259        28015 :     integer, allocatable :: temp(:)
     260        28015 :     self%size=self%size+1
     261        28015 :     if(self%size==1) then
     262           27 :       self%capacity=8
     263           27 :       ABI_MALLOC(self%data, (self%capacity))
     264        27988 :     else if ( self%size>self%capacity ) then
     265          208 :       self%capacity = self%size + self%size / 4 + 8
     266          624 :       ABI_MALLOC(temp, (self%capacity))
     267       127026 :       temp(:self%size-1) = self%data
     268              :       !temp gets deallocated
     269          208 :       ABI_MOVE_ALLOC(temp, self%data)
     270              :     end if
     271        28015 :     self%data(self%size)=val
     272              : 
     273        28015 : end subroutine int_array_type_push
     274              : !!***
     275              : 
     276              : 
     277              : !----------------------------------------------------------------------
     278              : !> @brief insertion_sort_int: sort a array using insertion sort algorithm
     279              : !>  it is a memory safe method but is generally slow.
     280              : !> @param[inout]  a: the array to be sorted. and will output inplace
     281              : !> @param[inout] order (optional) the sorted index, it can be used to sort
     282              : !>  other arrays so that the order in consistent.
     283              : !----------------------------------------------------------------------
     284            0 : subroutine insertion_sort_int(a, order)
     285              :   integer, intent(inout) :: a(:)
     286              :   integer, optional, intent(inout):: order(size(a))
     287              :   integer :: n,i,j, v
     288            0 :   n=size(a)
     289            0 :   if (present(order)) then
     290            0 :      do i = 1,n
     291            0 :         order(i)=i
     292              :      end do
     293              :   end if
     294            0 :   do i = 2,n
     295            0 :      v=a(i)
     296            0 :      j=i-1
     297            0 :      do while(j>=1 )
     298            0 :         if (a(j)<=v) exit
     299            0 :         a(j+1)=a(j)
     300            0 :         if(present(order)) order(j+1)=order(j)
     301            0 :         j=j-1
     302              :      end do
     303            0 :      a(j+1)=v
     304            0 :      if(present(order)) order(j+1)=i
     305              :   end do
     306              : 
     307            0 : end subroutine insertion_sort_int
     308              : 
     309              : !----------------------------------------------------------------------
     310              : !> @brief int_array_type_insertion_sort: sort a DYNAMIC INT array using insertion sort algorithm
     311              : !>  it is a memory safe method but is generally slow.
     312              : !> @param[inout]  a: an dynamic array. the array to be sorted. and will output inplace
     313              : !> @param[inout] order (optional) the sorted index, it can be used to sort
     314              : !>  other arrays so that the order in consistent.
     315              : !----------------------------------------------------------------------
     316              : subroutine int_array_type_insertion_sort(self, order)
     317              :   class(int_array_type), intent(inout):: self
     318              :   integer, optional, intent(inout):: order(self%size)
     319              :   integer :: i,j, v
     320              :   if (present(order)) then
     321              :      do i = 1, self%size
     322              :         order(i)=i
     323              :      end do
     324              :   end if
     325              :   do i = 2, self%size
     326              :      v=self%data(i)
     327              :      j=i-1
     328              :      do while(j>=1 )
     329              :         if(.not. self%data(j)>v) exit
     330              :         self%data(j+1)=self%data(j)
     331              :         if(present(order)) order(j+1)=order(j)
     332              :         j=j-1
     333              :      end do
     334              :      self%data(j+1)=v
     335              :      if(present(order)) order(j+1)=i
     336              :   end do
     337              : end subroutine int_array_type_insertion_sort
     338              : 
     339              : 
     340              : !----------------------------------------------------------------------
     341              : !> @brief int_array_type_insertion_sort: sort a DYNAMIC INT array using merge sort algorithm
     342              : !> @param[inout]  a: an dynamic array. the array to be sorted. and will output inplace
     343              : !> @param[inout] order (optional) the sorted index, it can be used to sort
     344              : !>  other arrays so that the order in consistent.
     345              : !----------------------------------------------------------------------
     346            0 : subroutine int_array_type_sort(self, order)
     347              :   class(int_array_type), intent(inout):: self
     348              :   integer, optional, intent(inout):: order(self%size)
     349            0 :   integer :: work((self%size+1)/2), work_order((self%size+1)/2)
     350            0 :   call MergeSort(self%data(:self%size), work, order, work_order)
     351            0 : end subroutine int_array_type_sort
     352              : 
     353              : 
     354              : !****f* m_dynarray/int_array_type_concate
     355              : !!
     356              : !! NAME
     357              : !! int_array_type_concate
     358              : !!
     359              : !! FUNCTION
     360              : !! concate int_array to a int_array_type
     361              : !!
     362              : !! INPUTS
     363              : !! self = int_array_type object
     364              : !! array= array to be concateed
     365              : !! OUTPUT
     366              : !! int_array<type(real_array_type)()> = int_array_type data
     367              : !! SOURCE
     368            0 : subroutine int_array_type_concate(self, array)
     369              :   class(int_array_type), intent(inout):: self
     370              :   class(int_array_type), intent(in):: array
     371              :   integer :: i
     372            0 :   do i=1, array%size
     373            0 :     call self%push(array%data(i))
     374              :   end do
     375            0 : end subroutine int_array_type_concate
     376              : !!***
     377              : 
     378              : 
     379              : 
     380              : 
     381              : 
     382              : !****f* m_dynarray/int_array_type_finalize
     383              : !!
     384              : !! NAME
     385              : !! int_array_type_finalize
     386              : !!
     387              : !! FUNCTION
     388              : !! destroy int_array_type
     389              : !!
     390              : !! INPUTS
     391              : !! self= int_array_type object
     392              : !! OUTPUT
     393              : !! int_array<type(int_array_type)()> = int_array_type data
     394              : !! SOURCE
     395           39 : subroutine int_array_type_finalize(self)
     396              : 
     397              :   class(int_array_type), intent(inout):: self
     398           39 :   ABI_SFREE(self%data)
     399           39 :   self%size=0
     400           39 :   self%capacity=0
     401              : 
     402           39 : end subroutine int_array_type_finalize
     403              : 
     404           27 : subroutine int_array_type_allgatherv(self,buff, comm, nproc)
     405              :   class(int_array_type), intent(inout):: self
     406              :   integer, intent(in) :: comm, nproc
     407              :   integer, allocatable, intent(out) :: buff(:)
     408              :   integer, allocatable :: tmp(:)
     409           54 :   integer :: disps(nproc), sizes(nproc)
     410              :   integer :: totsize, ierr, i
     411           27 :   totsize=self%size
     412           27 :   call xmpi_sum(totsize, comm, ierr)
     413           81 :   ABI_MALLOC(buff, (totsize))
     414           27 :   call xmpi_allgather(self%size, sizes, comm, ierr)
     415           27 :   disps(1)=0
     416           69 :   do i=2, nproc
     417           69 :     disps(i)=disps(i-1)+sizes(i-1)
     418              :   end do
     419           81 :   ABI_MALLOC(tmp, (self%size))
     420           27 :   if(self%size>0) then
     421           57 :     tmp(:)=self%data(:self%size)
     422              :   end if
     423           27 :   call xmpi_allgatherv(tmp, self%size, buff, sizes, disps, comm, ierr  )
     424           27 :   ABI_FREE(tmp)
     425           27 : end subroutine int_array_type_allgatherv
     426              : 
     427              : !==================================================================
     428              : 
     429              : !****f* m_dynarray/int2d_array_type_push
     430              : !!
     431              : !! NAME
     432              : !! int2d_array_type_push
     433              : !!
     434              : !! FUNCTION
     435              : !! push data to a int2d_array_type
     436              : !!
     437              : !! INPUTS
     438              : !! self = int2d_array_type object
     439              : !! val= data to be pushed
     440              : !! OUTPUT
     441              : !! int_array<type(real_array_type)()> = int2d_array_type data
     442              : !! SOURCE
     443      2571053 : subroutine int2d_array_type_push(self, val)
     444              : 
     445              :     class(int2d_array_type), intent(inout):: self
     446              :     integer :: val(:)
     447      2571053 :     integer, allocatable :: temp(:,:)
     448      2571053 :     if(self%size1<0) then
     449          113 :       self%size1=size(val)
     450      2570940 :     else if(self%size1 /= size(val)) then
     451            0 :       ABI_BUG("The size of  the array is inconsistent with the 2d dynamic array")
     452              :     end if
     453      2571053 :     self%size=self%size+1
     454      2571053 :     if(self%size==1) then
     455         1038 :       self%capacity=8
     456         4152 :       ABI_MALLOC(self%data, (size(val), self%capacity))
     457      2570015 :     else if ( self%size>self%capacity ) then
     458         1342 :       self%capacity = self%size + self%size / 4 + 8
     459         5368 :       ABI_MALLOC(temp, (size(val), self%capacity))
     460     42790057 :       temp(:,:self%size-1) = self%data
     461         1342 :       ABI_MOVE_ALLOC(temp, self%data) !temp gets deallocated
     462              :     end if
     463      9075108 :     self%data(:,self%size)=val
     464      2571053 : end subroutine int2d_array_type_push
     465              : !!***
     466              : 
     467              : !****f* m_dynarray/int2d_array_type_concate
     468              : !!
     469              : !! NAME
     470              : !! int2d_array_type_concate
     471              : !!
     472              : !! FUNCTION
     473              : !! concate int2d_array to a int2d_array_type
     474              : !!
     475              : !! INPUTS
     476              : !! self = int2d_array_type object
     477              : !! array= array to be concateed
     478              : !! OUTPUT
     479              : !! int_array<type(real_array_type)()> = int2d_array_type data
     480              : !! SOURCE
     481         1404 : subroutine int2d_array_type_concate(self, array)
     482              :   class(int2d_array_type), intent(inout):: self
     483              :   class(int2d_array_type), intent(in):: array
     484              :   integer :: i
     485         8660 :   do i=1, array%size
     486         8660 :     call self%push(array%data(:, i))
     487              :   end do
     488         1404 : end subroutine int2d_array_type_concate
     489              : !!***
     490              : 
     491            0 : subroutine int_array_type_tostatic(self, a)
     492              :   class(int_array_type), intent(inout):: self
     493              :   integer, allocatable :: a(:)
     494            0 :   if(self%size>0) then
     495            0 :     ABI_MALLOC(a, (self%size))
     496            0 :     a(:) = self%data(:self%size)
     497              :   else
     498            0 :     ABI_MALLOC(a, (self%size))
     499              :   end if
     500            0 : end subroutine int_array_type_tostatic
     501              : !!***
     502              : 
     503              : 
     504              : 
     505           38 : subroutine int2d_array_type_tostatic(self, a, size1)
     506              :   class(int2d_array_type), intent(inout):: self
     507              :   integer, allocatable :: a(:, :)
     508              :   integer, optional :: size1
     509           38 :   if(self%size>0) then
     510          152 :     ABI_MALLOC(a, (self%size1, self%size))
     511        29556 :     a(:, :) = self%data(:, :self%size)
     512            0 :   else if(present(size1)) then
     513            0 :     ABI_MALLOC(a, (size1, self%size))
     514              :   else
     515            0 :     ABI_BUG("the size of the 2darray is unkown.")
     516              :   end if
     517           38 : end subroutine int2d_array_type_tostatic
     518              : !!***
     519              : 
     520              : 
     521              : 
     522              : 
     523              : !****f* m_dynarray/int2d_array_type_push
     524              : !!
     525              : !! NAME
     526              : !! int2d_array_type_push
     527              : !!
     528              : !! FUNCTION
     529              : !! push data to a int2d_array_type
     530              : !!
     531              : !! INPUTS
     532              : !! self = int2d_array_type object
     533              : !! val= data to be pushed
     534              : !! OUTPUT
     535              : !! int_array<type(real_array_type)()> = int2d_array_type data
     536              : !! SOURCE
     537        11644 : subroutine int2d_array_type_push_unique(self, val, position)
     538              : 
     539              :     class(int2d_array_type), intent(inout):: self
     540              :     integer, intent(in) :: val(:)
     541              :     integer, optional, intent(out) :: position
     542              :     integer :: i
     543              :     logical :: inside
     544        11644 :     inside=.False.
     545       106266 :     do i=1, self%size
     546       175210 :        if(all(self%data(:,i)==val)) then
     547        11438 :           inside=.True.
     548        11438 :           if (present(position)) position=i
     549              :           exit
     550              :        endif
     551              :     enddo
     552              :     if(.not. inside) then
     553          206 :        call self%push(val)
     554          206 :        if (present(position)) position=self%size
     555              :     end if
     556        11644 :   end subroutine int2d_array_type_push_unique
     557              : !!***
     558              : 
     559              : 
     560              : 
     561              : !****f* m_dynarray/int2d_array_type_finalize
     562              : !!
     563              : !! NAME
     564              : !! int2d_array_type_finalize
     565              : !!
     566              : !! FUNCTION
     567              : !! destroy int2d_array_type
     568              : !!
     569              : !! INPUTS
     570              : !! self= int2d_array_type object
     571              : !! OUTPUT
     572              : !! int_array<type(int2d_array_type)()> = int2d_array_type data
     573              : !! SOURCE
     574         2419 : subroutine int2d_array_type_finalize(self)
     575              : 
     576              :   class(int2d_array_type), intent(inout):: self
     577         2419 :   if ( allocated(self%data) ) then
     578         1038 :       ABI_SFREE(self%data)
     579              :   end if
     580         2419 :   self%size=0
     581         2419 :   self%capacity=0
     582              : 
     583         2419 : end subroutine int2d_array_type_finalize
     584              : 
     585              : !----------------------------------------------------------------------
     586              : !> @brief sort a 2D DYNAMIC INT array using insertion sort algorithm
     587              : !>  it is a memory safe method but is generally slow.
     588              : !> it compares the elements in first dimension i.e. A(:, i) and sort the second dim.
     589              : !>  The comparing is from left to right.
     590              : !> @param[inout]  a: an dynamic array. the array to be sorted. and will output inplace
     591              : !> @param[inout] order (optional) the sorted index, it can be used to sort
     592              : !>  other arrays so that the order in consistent.
     593              : !----------------------------------------------------------------------
     594              : 
     595              : subroutine int2d_array_type_insertion_sort(self, order)
     596              :   class(int2d_array_type), intent(inout):: self
     597              :   integer, optional, intent(inout):: order(self%size)
     598              :   integer :: i,j, v(size(self%data, dim=1))
     599              :   if (present(order)) then
     600              :      do i = 1, self%size
     601              :         order(i)=i
     602              :      end do
     603              :   end if
     604              :   do i = 2, self%size
     605              :      v(:)=self%data(:,i)
     606              :      j=i-1
     607              :      do while(j>=1)
     608              :         if (.not. (array_morethan(self%data(:,j),v, size(self%data, dim=1)))) exit
     609              :         self%data(:,j+1)=self%data(:,j)
     610              :         if(present(order)) order(j+1)=order(j)
     611              :         j=j-1
     612              :      end do
     613              :      self%data(:,j+1)=v(:)
     614              :      if(present(order)) order(j+1)=i
     615              :   end do
     616              :   self%sorted=.True.
     617              : end subroutine int2d_array_type_insertion_sort
     618              : 
     619              : 
     620              : !----------------------------------------------------------------------
     621              : !> @brief sort a 2D DYNAMIC INT array using merge sort algorithm
     622              : !>  It is now set as the default sorting algorithm.
     623              : !>  it is a memory safe method but is generally slow.
     624              : !> it compares the elements in first dimension i.e. A(:, i) and sort the second dim.
     625              : !>  The comparing is from left to right.
     626              : !> @param[inout]  a: an dynamic array. the array to be sorted. and will output inplace
     627              : !> @param[inout] order (optional) the sorted index, it can be used to sort
     628              : !>  other arrays so that the order in consistent.
     629              : !----------------------------------------------------------------------
     630              : 
     631           12 : subroutine int2d_array_type_sort(self, order)
     632              :   class(int2d_array_type), intent(inout):: self
     633              :   integer, optional, intent(inout):: order(self%size)
     634           24 :   integer :: work(size(self%data, dim=1), (self%size+1)/2), work_order((self%size+1)/2)
     635           12 :   call MergeSort2D(self%data(:, :self%size), work, order, work_order )
     636           12 : end subroutine int2d_array_type_sort
     637              : 
     638              : 
     639              : !----------------------------------------------------------------------
     640              : !> @brief binary search
     641              : !>
     642              : !> @param[in] self: the 2D array to be searched from
     643              : !> @param[in] val: the value to be searched
     644              : !> @param[out] i: the index of the first one found. returns 0 if not found.
     645              : !----------------------------------------------------------------------
     646              : 
     647            0 : function int2d_array_type_binsearch(self, val) result(i)
     648              :   class(int2d_array_type), intent(inout):: self
     649              :   integer, intent(inout) :: val(:)
     650              :   integer :: i
     651            0 :   i=binsearch_left_integerlist(self%data(:,1:self%size), val)
     652            0 : end function int2d_array_type_binsearch
     653              : 
     654              : 
     655              : 
     656              : !====================== Unit tests======================
     657              : 
     658            0 : subroutine binsearch_test()
     659              :   integer :: a(4)=[1,2,3,4], b(3,3)=reshape([0,0,0,0,1,0,1,0,0], [3,3])
     660              :   integer :: i
     661            0 :   i=binsearch_left_integer(a, 5)
     662            0 :   i=binsearch_left_integerlist(b, [0,0,0])
     663            0 : end subroutine binsearch_test
     664              : 
     665            0 : subroutine insertion_sort_int_test()
     666              :   integer :: a(4), order(4), b(4), a2(8)
     667            0 :   a=[1,5,3,4]
     668            0 :   b=a
     669            0 :   call insertion_sort_int(a, order)
     670            0 :   a2=[3,6,2,4, 3, 5, 0, 9]
     671            0 :   call insertion_sort_int(a2)
     672            0 : end subroutine insertion_sort_int_test
     673              : 
     674            0 : subroutine int2d_array_test()
     675            0 :   type(int2d_array_type) :: t
     676            0 :   call t%push_unique([1,1,2])
     677            0 :   call t%push_unique([1,2,2])
     678            0 :   call t%push_unique([1,1,2])
     679            0 :   call t%push_unique([1,1,1])
     680            0 :   call t%push_unique([-1, 3, 3])
     681            0 :   call t%push_unique([2,1, 4])
     682            0 :   call t%sort()
     683            0 : end subroutine int2d_array_test
     684              : 
     685            0 : subroutine dynamic_array_unittest()
     686            0 :   call binsearch_test()
     687            0 :   call insertion_sort_int_test()
     688            0 :   call int2d_array_test()
     689            0 : end subroutine dynamic_array_unittest
     690              : 
     691              : 
     692            0 : end module m_dynamic_array
     693              : !!***
        

Generated by: LCOV version 2.3-1