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 : !!***
|