FMUTIL  0.1
Fortran Miscellaneous UTILities
vector.f90
Go to the documentation of this file.
1 !##############################################################################
2 ! ________ _____ ______________
3 ! / ____/ |/ / / / /_ __/ _/ /
4 ! / /_ / /|_/ / / / / / / / // /
5 ! / __/ / / / / /_/ / / / _/ // /___
6 ! /_/ /_/ /_/\____/ /_/ /___/_____/
7 !
8 ! Copyright 2020 Bharat Mahajan
9 !
10 ! Licensed under the Apache License, Version 2.0 (the "License");
11 ! you may not use this file except in compliance with the License.
12 ! You may obtain a copy of the License at
13 !
14 ! http://www.apache.org/licenses/LICENSE-2.0
15 !
16 ! Unless required by applicable law or agreed to in writing, software
17 ! distributed under the License is distributed on an "AS IS" BASIS,
18 ! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19 ! See the License for the specific language governing permissions and
20 ! limitations under the License.
21 !
28 !
29 !##############################################################################
30 
31 
32 module vectors
33 
34  use fmutilbase
35 
36  implicit none
37 
38  private
39 
41  integer, parameter :: default_bktcap = 3
42 
44  integer, parameter :: default_newbktsallocated = 2
45 
48  type, abstract, public :: vecelem
49  contains
52  procedure(assign_vecelem), deferred :: assignvecelem
54  generic, public :: assignment(=) => assignvecelem
55  end type vecelem
56 
57  abstract interface
58 
59  subroutine assign_vecelem(lhs, rhs)
60  import :: vecelem
61  implicit none
62  class(vecelem), intent(out) :: lhs
63  class(vecelem), intent(in) :: rhs
64  end subroutine assign_vecelem
65  end interface
66 
68  type, public, extends(vecelem) :: invalidvecelem
69  private
72  logical :: invalid = .true.
73  contains
74  private
75  procedure, public :: assignvecelem => assign_invalidelem
76  end type invalidvecelem
77 
79  type, private :: bkt
80  private
82  class(vecelem), dimension(:), allocatable :: bktdata
84  logical, dimension(:), allocatable :: slotfree
85  contains
86  private
88  procedure :: bktinit
90  procedure :: bktclear
92  procedure :: add_bktelem
94  procedure :: del_bktelem
96  procedure :: bktelem
98  procedure :: bktsliceptr
100  procedure :: is_bktempty
102  procedure :: bktsz
103  end type bkt
104 
106  type :: bktptr
107  type(bkt), pointer :: pbkt => null()
108  end type bktptr
109 
111  type, public :: vector
112 
113  private
114 
116  integer, public :: status = 0
117 
119  logical :: storageallocated = .false.
120 
122  integer :: newbktstoallocate = default_newbktsallocated
123 
125  integer :: bktcap = default_bktcap
126 
128  integer :: usedbkts = 0
129 
131  integer :: allocatedbkts = 0
132 
134  class(vecelem), allocatable :: moldelem
135 
137  type(bktptr), dimension(:), allocatable :: vecdata
138 
139  contains
140 
141  private
142 
143  procedure :: assignvector
144 
149  generic, public :: assignment(=) => assignvector
150 
151  ! Internal procedures
152  procedure :: create_newbkts
153  procedure :: index2bkt
154 
156  procedure, public :: init => initialize
157 
159  procedure, public :: size => vec_size
160 
162  procedure, public :: capacity
163 
165  procedure, public :: nusedbkts
166 
169  procedure, public :: reserve
170 
173  procedure, public :: shrinktofit
174 
176  procedure, public :: pushback => push_back
177 
179  procedure, public :: popback => pop_back
180 
182  procedure, public :: elemat => elem_at
183 
185  procedure, public :: front => elem_front
186 
188  procedure, public :: back => elem_back
189 
193  procedure, public :: slice => vec_slice
194 
200  procedure, public :: bktslice => bkt_slice
201 
204  procedure, public :: insert => elem_insert
205 
208  procedure, public :: erase => elem_erase
209 
211  procedure, public :: clear
212 
214  final :: destroy
215 
216  end type vector
217 
218 
219 
220  contains
221 
222 
223 
231  subroutine initialize(me, NewBktsToAllocate, BktCap, MoldElem)
232  implicit none
233 
234  class(vector), intent(inout) :: me
236  integer, intent(in), optional :: NewBktsToAllocate
239  integer, intent(in), optional :: BktCap
241  class(vecelem), intent(in), optional :: MoldElem
242 
243  ! Set the number of new buckets to allocate when last bucket is full
244  if (present(newbktstoallocate)) me%NewBktsToAllocate = newbktstoallocate
245 
246  ! If Vector is already initialized, we are done
247  if (me%StorageAllocated) return
248 
249  if (present(bktcap)) me%BktCap = bktcap
250 
251  ! if mold_elem is provided, then allocate initial buckets
252  if (present(moldelem)) then
253  allocate(me%MoldElem, source=moldelem)
254  call me%create_newbkts(me%NewBktsToAllocate)
255  end if
256  ! If successful, start using the first bucket
257  if (me%status == 0) then
258  me%StorageAllocated = .true.
259  me%UsedBkts = 1
260  end if
261  end subroutine initialize
262 
263 
264 
265 
267  pure function vec_size(me)
268  implicit none
269  class(vector), intent(in) :: me
270  integer :: vec_size
271 
272  vec_size = 0
273  ! if not allocated size is 0
274  if ((.NOT. me%StorageAllocated) .OR. me%UsedBkts == 0) return
275 
276  ! N-1 full bkts and Nth partial filled bkts
277  vec_size = (me%UsedBkts-1)*me%BktCap &
278  + me%VecData(me%UsedBkts)%pBkt%bktsz()
279  end function vec_size
280 
281 
282 
285  pure function capacity(me)
286  implicit none
287  class(vector), intent(in) :: me
288  integer :: capacity
289 
290  capacity = me%AllocatedBkts*me%BktCap
291  end function capacity
292 
293 
297  pure function nusedbkts(me)
298  implicit none
299  class(vector), intent(in) :: me
300  integer :: nusedbkts
301 
302  nusedbkts = me%UsedBkts
303  end function nusedbkts
304 
305 
306 
307 
309  subroutine reserve(me, n)
310  implicit none
311  class(vector), intent(inout) :: me
313  integer, intent(in) :: n
314 
315  integer :: NumBkts
316 
317  real :: fracbkts
318 
319  ! required number of new bkts
320  fracbkts = n
321  numbkts = ceiling(fracbkts/me%BktCap) - me%AllocatedBkts
322 
323  if (numbkts > 0) then
324  call me%create_newbkts(numbkts)
325  end if
326  end subroutine reserve
327 
328 
329 
330 
332  subroutine shrinktofit(me)
333  implicit none
334  class(vector), intent(inout) :: me
335 
336  type(bktptr), dimension(:), allocatable :: tmp
337  integer :: ctr
338 
339  ! deallocate if used bkts are less than allocated bkts
340  if (me%UsedBkts < me%AllocatedBkts) then
341  do ctr = me%Size()+1, me%AllocatedBkts
342  if (associated(me%VecData(ctr)%pBkt)) deallocate(me%VecData(ctr)%pBkt)
343  me%VecData(ctr)%pBkt => null()
344  end do
345  me%AllocatedBkts = me%UsedBkts
346  end if
347 
348  if (me%AllocatedBkts < 1) then
349  ! if all storage deallocated, then set the flag
350  me%StorageAllocated = .false.
351  if (allocated(me%VecData)) deallocate(me%VecData, stat=me%status)
352  else
353  ! shrink the bucket pointer array
354  allocate(tmp(1:me%AllocatedBkts), stat=me%status)
355  if (me%status == 0) then
356  tmp = me%VecData(1:me%AllocatedBkts)
357  call move_alloc(from=tmp, to=me%VecData)
358  end if
359  end if
360  end subroutine shrinktofit
361 
362 
363 
366  function elem_at(me, Index) result(elem)
367  implicit none
368  class(vector), intent(inout) :: me
370  integer, intent(in) :: index
372  class(vecelem), pointer :: elem
373 
374  integer :: bktnum, offset
375 
376  ! compute bucket number and offset
377  call me%Index2Bkt(index, bktnum, offset)
378 
379  if (bktnum > 0 .AND. bktnum <= me%UsedBkts &
380  .AND. offset > 0 .AND. offset <= me%BktCap) then
381  elem => me%VecData(bktnum)%pBkt%bktelem(offset)
382  else
383  ! incorrect index
384  elem => null()
385  end if
386  end function elem_at
387 
388 
390  function elem_front(me) result(elem)
391  implicit none
392  class(vector), intent(inout) :: me
393  class(vecelem), allocatable :: elem
394 
395  allocate(elem, source=me%ElemAt(1))
396  end function elem_front
397 
398 
399 
401  function elem_back(me) result(elem)
402  implicit none
403  class(vector), intent(inout) :: me
404  class(vecelem), allocatable :: elem
405 
406  integer :: index
407  index = (me%UsedBkts-1)*me%BktCap &
408  + me%VecData(me%UsedBkts)%pBkt%bktsz()
409  allocate(elem, source=me%ElemAt(index))
410  end function elem_back
411 
412 
413 
414 
419  function vec_slice(me, lower, upper, stride) result(arr)
420  implicit none
421  class(vector), intent(inout) :: me
422 
424  integer, intent(in) :: lower
427  integer, intent(in) :: upper
430  integer, intent(in), optional :: stride
432  class(vecelem), dimension(:), allocatable :: arr
433 
434  integer :: step, ctr, sz, vecsz
435  integer, dimension(:), allocatable :: elemindices
436 
437  if (present(stride)) then
438  step = stride
439  else
440  step = 1
441  end if
442 
443  ! create indices of the requested elements
444  elemindices = [(ctr, ctr = lower, upper, step)]
445 
446  ! allocate memory
447  sz = size(elemindices)
448  vecsz = me%Size()
449  if (sz < 1 .OR. vecsz < 1 &
450  .OR. elemindices(1) < 1 .OR. elemindices(1) > vecsz &
451  .OR. elemindices(sz) < 1 .OR. elemindices(sz) > vecsz) then
452  ! If Vector is empty or requested slice is 0 size then
453  ! return 0-sized array
454  allocate(invalidvecelem:: arr(0), stat=me%status)
455  return
456  else
457  allocate(arr(sz), mold=me%VecData(1)%pBkt%bktelem(1), &
458  stat=me%status)
459  end if
460 
461  ! fill the array with data to return
462  do ctr = 1, sz
463  block
464  integer :: bkt, offset
465  call me%Index2Bkt(elemindices(ctr), bkt, offset)
466  arr(ctr) = me%VecData(bkt)%pBkt%bktelem(offset)
467  end block
468  end do
469  end function vec_slice
470 
471 
472 
473 
482  function bkt_slice(me, lower, upper) result(ptr)
483  implicit none
484  class(vector), intent(inout) :: me
485 
487  integer, intent(in) :: lower
493  integer, intent(inout) :: upper
495  class(vecelem), dimension(:), pointer :: ptr
496 
497  integer :: bktl, offsetl, bktu, offsetu, ub, vecsz, ctr
498  logical :: boundsvalid
499 
500  ptr => null()
501 
502  ! check for bounds
503  vecsz = me%Size()
504  boundsvalid = .true.
505  if (lower < 1 .OR. lower > vecsz) boundsvalid = .false.
506  if ((upper > lower .AND. upper > vecsz) &
507  .OR. upper < lower .AND. upper < 1) boundsvalid = .false.
508 
509  if (boundsvalid) then
510  call me%Index2Bkt(lower, bktl, offsetl)
511  call me%Index2Bkt(upper, bktu, offsetu)
512  ! check whether the both bounds lie in the same bucket
513  if (bktl /= bktu) then
514  ! truncate the slice to bucket boundary
515  if (upper < lower) then
516  ! slice is from lower bound to start of the bucket
517  upper = (bktl-1)*me%BktCap + 1
518  ptr => me%VecData(bktl)%pBkt%bktsliceptr(offsetl,1)
519  else
520  ! slice is from lower bound to end of the bucket
521  upper = bktl*me%BktCap
522  ptr => me%VecData(bktl)%pBkt%bktsliceptr(offsetl,me%BktCap)
523  end if
524  else
525  ! slice is from lower to upper bound
526  ptr => me%VecData(bktl)%pBkt%bktsliceptr(offsetl,offsetu)
527  end if
528  end if
529  end function bkt_slice
530 
531 
533  function push_back(me, velem) result(Index)
534  implicit none
535  class(vector), intent(inout) :: me
537  class(vecelem), intent(in) :: velem
539  integer :: index
540 
541  integer :: offset
542 
543  index = 0
544  if (.NOT. me%StorageAllocated) then
545  ! allocate buckets for the first time
546  allocate(me%MoldElem, source=velem)
547  call me%create_newbkts(me%NewBktsToAllocate)
548  if (me%status /= 0) return
549  ! use the newly created first bucket
550  me%UsedBkts = 1
551  end if
552 
553  ! extract the index of the last occupied slot in bucket
554  if (me%AllocatedBkts > 0 .AND. me%UsedBkts < 1) me%UsedBkts = 1
555  offset = me%VecData(me%UsedBkts)%pBkt%bktsz() + 1
556 
557  ! if bucket is full then allocate more buckets
558  if (offset > me%BktCap) then
559  ! allocate new buckets
560  call me%create_newbkts(me%NewBktsToAllocate)
561  if (me%status /= 0) return
562  ! use the newly created bucket
563  me%UsedBkts = me%UsedBkts + 1
564  offset = 1
565  end if
566 
567  ! copy the elem at the back of the bucket
568  call me%VecData(me%UsedBkts)%pBkt%add_bktelem(offset, velem)
569  index = offset + (me%UsedBkts-1)*me%BktCap
570 
571  end function push_back
572 
573 
574 
575 
577  function pop_back(me) result(velem)
578  implicit none
579  class(vector), intent(inout) :: me
580  class(vecelem), allocatable :: velem
581 
582  integer :: bktind
583 
584  ! get the last element
585  bktind = me%vecdata(me%UsedBkts)%pBkt%bktsz()
586  allocate(velem, source=me%VecData(me%UsedBkts)%pBkt%bktelem(bktind))
587 
588  ! delete this element
589  call me%VecData(me%UsedBkts)%pBkt%del_bktelem(bktind)
590 
591  ! if this bucket is empty, then update used bucket counter
592  if (me%vecdata(me%UsedBkts)%pBkt%is_bktempty()) then
593  me%UsedBkts = me%UsedBkts - 1
594  end if
595  end function pop_back
596 
597 
598 
599 
600 
605  subroutine elem_insert(me, pos, NewElems, count)
606  implicit none
607  class(vector), intent(inout) :: me
610  integer, intent(in) :: pos
612  class(vecelem), dimension(:), intent(in) :: NewElems
616  integer, intent(in), optional :: count
617 
618  integer :: countval, reqdslots, emptyslots, newbkts, ctr, sz, vecsz
619  integer :: Bkt0, Offset0, Bkt1, Offset1, ctr1, ctr2
620  real :: tmp
621 
622  countval = 1
623  if (present(count)) countval = count
624 
625  ! if empty array is passed, nothing to be done
626  sz = size(newelems)
627  vecsz = me%Size()
628  if (sz < 1) return
629 
630  ! if vector is not already allocated, do it now
631  if (.NOT. me%StorageAllocated) then
632  ! allocate buckets for the first time
633  allocate(me%MoldElem, source=newelems(1))
634  call me%create_newbkts(me%NewBktsToAllocate)
635  if (me%status /= 0) return
636  ! use the newly created first bucket
637  me%UsedBkts = 1
638  end if
639 
640  ! check for parameters
641  if (pos < 1 .OR. countval < 1 .OR. ((pos-vecsz) > 1)) then
642  me%status = -1
643  return
644  end if
645 
646  ! Expand Vector for new elements
647  reqdslots = countval*sz
648  emptyslots = me%Capacity() - me%Size()
649  tmp = reqdslots - emptyslots
650  newbkts = ceiling(tmp/me%BktCap)
651 
652  if (newbkts > 0) then
653  ! allocate new buckets
654  call me%create_newbkts(newbkts)
655  end if
656 
657  ! First Bucket for the new elements
658  call me%Index2Bkt(pos, bkt0, offset0)
659  ! First Bucket for the moved elements
660  call me%Index2Bkt(pos+countval*sz, bkt1, offset1)
661 
662  ! Move old element to the new empty locations
663  reqdslots = me%Size() - pos + 1
664  ctr1 = bkt0
665  ctr2 = offset0
666  do ctr = 1, reqdslots
667  ! Move old element to the new empty location
668 
669  call me%VecData(bkt1)%pBkt%add_bktelem(offset1, &
670  me%VecData(bkt0)%pBkt%bktelem(offset0))
671 
672  call me%VecData(bkt0)%pBkt%del_bktelem(offset0)
673 
674  ! increment counters
675  offset0 = offset0 + 1
676  offset1 = offset1 + 1
677  if (offset0 > me%BktCap) then
678  offset0 = 1
679  bkt0 = bkt0 + 1
680  end if
681  if (offset1 > me%BktCap) then
682  offset1 = 1
683  bkt1 = bkt1 + 1
684  end if
685  end do
686 
687  ! copy the new element in the old location
688  bkt0 = ctr1
689  offset0 = ctr2
690  ctr1 = 1
691  do ctr = 1, countval*sz
692  ! copy the new element in the old location
693  call me%VecData(bkt0)%pBkt%add_bktelem(offset0, newelems(ctr1))
694  ! increment counters
695  ctr1 = ctr1 + 1
696  if (ctr1 > sz) ctr1 = 1
697  offset0 = offset0 + 1
698  if (offset0 > me%BktCap) then
699  offset0 = 1
700  bkt0 = bkt0 + 1
701  end if
702  end do
703 
704  ! update the buckets used
705  me%UsedBkts = me%usedBkts + newbkts
706 
707  end subroutine elem_insert
708 
709 
710 
711 
712 
716  subroutine elem_erase(me, lower, upper)
717  implicit none
718  class(vector), intent(inout) :: me
719 
720  integer, intent(In) :: lower
724  integer, intent(In), optional :: upper
725 
726  integer :: sz, ctr, upperval
727  integer :: Bkt0, Offset0, Bkt1, Offset1
728 
729  ! parameter checks
730  sz = me%Size()
731  if (lower < 1 .OR. lower > sz .OR. sz < 1) return
732 
733  if (present(upper)) then
734  if (lower > upper) return
735  end if
736 
737  ! Location of the first element to be deleted
738  call me%Index2Bkt(lower, bkt0, offset0)
739 
740  ! Location of the element just after the last element to be deleted
741  if (present(upper)) then
742  upperval = upper + 1
743  call me%Index2Bkt(upperval, bkt1, offset1)
744  else
745  upperval = lower + 1
746  bkt1 = bkt0
747  offset1 = offset0 + 1
748  if (offset1 > me%BktCap) then
749  offset1 = 1
750  bkt1 = bkt1 + 1
751  end if
752  end if
753 
754  ! shift the other elements one by one
755  do ctr = 1, (sz - upperval + 1)
756  ! shift
757  call me%VecData(bkt0)%pBkt%add_bktelem(offset0, &
758  me%VecData(bkt1)%pBkt%bktelem(offset1))
759 
760  ! increment counters
761  offset0 = offset0 + 1
762  offset1 = offset1 + 1
763  if (offset0 > me%BktCap) then
764  offset0 = 1
765  bkt0 = bkt0 + 1
766  end if
767  if (offset1 > me%BktCap) then
768  offset1 = 1
769  bkt1 = bkt1 + 1
770  end if
771  end do
772 
773  ! Clear the empty slots in the last partially filled bkt
774  if (offset0 /= 1) then
775  do ctr = offset0, me%BktCap
776  call me%VecData(bkt0)%pBkt%del_bktelem(ctr)
777  end do
778  bkt0 = bkt0 + 1
779  end if
780  ! clear the extra buckets starting from Bkt0+1
781  do ctr = bkt0, bkt1
782  call me%VecData(ctr)%pBkt%bktclear()
783  end do
784  ! update number of used buckets
785  me%UsedBkts = bkt0 - 1
786 
787  end subroutine elem_erase
788 
789 
790 
791 
793  subroutine clear(me)
794  implicit none
795  class(vector), intent(inout) :: me
796 
797  integer :: ctr
798  ! clear bucket slots
799  do ctr = 1, me%UsedBkts
800  call me%VecData(ctr)%pBkt%bktclear()
801  end do
802  ! used buckets are 0 now
803  me%UsedBkts = 0
804  end subroutine clear
805 
806 
807 
808 
810  subroutine create_newbkts(me, NumBkts)
811  implicit none
812  class(vector), intent(inout) :: me
813 
814  integer, intent(in) :: NumBkts
815 
816  type(bktptr), dimension(:), allocatable :: tmp
817  integer :: ctr
818 
819  ! allocate new bucket array
820  allocate(tmp(me%AllocatedBkts+numbkts), stat=me%status)
821 
822  if (me%status == 0) then
823  ! if vector already has buckets
824  if (me%StorageAllocated) then
825  ! copy the previous bucket pointers
826  tmp(1:me%AllocatedBkts) = me%VecData
827  end if
828 
829  ! expand the bucket array
830  call move_alloc(from=tmp, to=me%VecData)
831 
832  ! allocate storage for new buckets
833  do ctr = 1, numbkts
834  allocate(me%VecData(me%AllocatedBkts+ctr)%pBkt, stat=me%status)
835  call me%VecData(me%AllocatedBkts+ctr)%pbkt%bktinit(me%status, &
836  me%BktCap, me%MoldElem)
837  if (me%status /= 0) exit
838  end do
839 
840  ! If the intended number of buckets are not allocated, init failed
841  if (ctr > numbkts) then
842  me%AllocatedBkts = me%AllocatedBkts + ctr - 1
843  me%StorageAllocated = .true.
844  else
845  me%status = -1
846  end if
847  end if
848  end subroutine create_newbkts
849 
850 
851 
853  pure subroutine index2bkt(me, Index, Bkt, BktOffset)
854  implicit none
855  class(vector), intent(in) :: me
856 
857  integer, intent(in) :: index
858  integer, intent(out) :: bkt
859  integer, intent(out) :: bktoffset
860 
861  real :: frac
862 
863  ! Bucket to which this index belongs
864  frac = index
865  frac = frac/me%BktCap
866  bkt = ceiling(frac)
867 
868  ! Offset into the bucket
869  bktoffset = index - (bkt-1)*me%BktCap
870  end subroutine
871 
872 
873  ! Do nothing for the invalid element assignement
874  subroutine assign_invalidelem(lhs, rhs)
875  implicit none
876  class(invalidvecelem), intent(out) :: lhs
877  class(vecelem), intent(in) :: rhs
878  end subroutine assign_invalidelem
879 
880 
882  subroutine assignvector(lhs, rhs)
883  implicit none
884  class(vector), intent(out) :: lhs
885  class(vector), intent(in) :: rhs
886 
887  integer :: ctr
888 
889  ! we assign the contents by moving all the buckets of rhs to lhs
890 
891  ! allocate memory for buckets array
892  allocate(lhs%VecData(size(rhs%VecData)))
893 
894  ! create buckets and mold elem
895  allocate(lhs%MoldElem, source=rhs%MoldElem)
896  do ctr = 1, rhs%AllocatedBkts
897  allocate(lhs%VecData(ctr)%pBkt, source=rhs%VecData(ctr)%pBkt)
898  end do
899 
900  ! copy Vector state
901  lhs%status = rhs%status
902  lhs%StorageAllocated = rhs%StorageAllocated
903  lhs%NewBktsToAllocate = rhs%NewBktsToAllocate
904  lhs%BktCap = rhs%BktCap
905  lhs%UsedBkts = rhs%UsedBkts
906  lhs%AllocatedBkts = rhs%AllocatedBkts
907 
908  end subroutine assignvector
909 
910 
912  subroutine destroy(me)
913  implicit none
914  type(vector), intent(inout) :: me
915 
916  integer :: ctr
917 
918  ! free up memory held up by all the buckets
919  do ctr = 1, size(me%VecData)
920  if (associated(me%VecData(ctr)%pBkt)) deallocate(me%VecData(ctr)%pBkt)
921  me%VecData(ctr)%pBkt => null()
922  end do
923  end subroutine destroy
924 
925 
927 
928  subroutine bktinit(me, status, cap, mold_elem)
929  implicit none
930  class(bkt), intent(inout) :: me
931  integer, intent(out) :: status
932  integer, intent(in) :: cap
933  class(vecelem), intent(in) :: mold_elem
934 
935  allocate(me%SlotFree(cap), stat=status)
936  allocate(me%BktData(cap), stat=status, mold=mold_elem)
937  me%SlotFree = .true.
938  end subroutine bktinit
939 
940 
941 
942  subroutine add_bktelem(me, offset, elem)
943  implicit none
944  class(bkt), intent(inout) :: me
945  integer, intent(in) :: offset
946  class(vecelem), intent(in) :: elem
947 
948  me%BktData(offset) = elem
949  me%SlotFree(offset) = .false.
950  end subroutine add_bktelem
951 
952 
953 
954  subroutine del_bktelem(me, offset)
955  implicit none
956  class(bkt), intent(inout) :: me
957  integer, intent(in) :: offset
958 
959  me%SlotFree(offset) = .true.
960  end subroutine del_bktelem
961 
962 
963  subroutine bktclear(me)
964  implicit none
965  class(bkt), intent(inout) :: me
966 
967  me%SlotFree = .true.
968  end subroutine bktclear
969 
970 
971 
972  function bktelem(me, offset)
973  implicit none
974  class(bkt), intent(in), target :: me
975  integer, intent(in) :: offset
976  class(vecelem), pointer :: bktelem
977 
978  if (.NOT. me%SlotFree(offset)) then
979  bktelem => me%BktData(offset)
980  else
981  bktelem => null()
982  end if
983  end function bktelem
984 
985 
986 
987  function bktsliceptr(me, start_ind, end_ind)
988  implicit none
989  class(bkt), intent(in), target :: me
990  integer, intent(in) :: start_ind, end_ind
991  class(vecelem), dimension(:), pointer :: bktsliceptr
992 
993  integer :: stride
994 
995  bktsliceptr => null()
996 
997  stride = 1
998  if (start_ind > end_ind) stride = -1
999 
1000  if (any(me%SlotFree(start_ind:end_ind:stride))) return
1001 
1002  bktsliceptr => me%BktData(start_ind:end_ind:stride)
1003  end function bktsliceptr
1004 
1005 
1006 
1007  pure function is_bktempty(me)
1008  implicit none
1009  class(bkt), intent(in) :: me
1010  logical :: is_bktempty
1011 
1012  is_bktempty = .false.
1013  if (all(me%SlotFree)) is_bktempty = .true.
1014  end function is_bktempty
1015 
1016 
1017 
1018  pure function bktsz(me)
1019  implicit none
1020  class(bkt), intent(in) :: me
1021  integer :: bktsz
1022  bktsz = count(.NOT. me%SlotFree)
1023  end function bktsz
1024 
1025 
1026 
1027 end module vectors
1028 
1029 
vectors::elem_front
class(vecelem) function, allocatable elem_front(me)
Returns the element with the index=1.
Definition: vector.f90:391
vectors::initialize
subroutine initialize(me, NewBktsToAllocate, BktCap, MoldElem)
Optional procedure to initialize Vector type and allocate internal storage. It can be used to modify ...
Definition: vector.f90:232
vectors::bktelem
class(vecelem) function, pointer bktelem(me, offset)
Definition: vector.f90:973
vectors::index2bkt
pure subroutine index2bkt(me, Index, Bkt, BktOffset)
Converts Vector index to bucket number and offset into the bucket.
Definition: vector.f90:854
vectors::create_newbkts
subroutine create_newbkts(me, NumBkts)
Subroutine to allocate storage for a new bucket.
Definition: vector.f90:811
vectors::assign_invalidelem
subroutine assign_invalidelem(lhs, rhs)
Definition: vector.f90:875
vectors::elem_erase
subroutine elem_erase(me, lower, upper)
Delete the element/elements between and including lower and upper bounds. The elements are moved to f...
Definition: vector.f90:717
vectors::vector
Vector type.
Definition: vector.f90:111
vectors::add_bktelem
subroutine add_bktelem(me, offset, elem)
Definition: vector.f90:943
vectors::del_bktelem
subroutine del_bktelem(me, offset)
Definition: vector.f90:955
vectors::nusedbkts
pure integer function nusedbkts(me)
Returns the total number of internal data buckets allocated by the Vector. Each bucket can contain mu...
Definition: vector.f90:298
vectors::clear
subroutine clear(me)
Clear the contents of Vector but the bucket memory is not deallocated.
Definition: vector.f90:794
vectors::shrinktofit
subroutine shrinktofit(me)
Deallocate unused buckets to make Capacity as close to Size as possible.
Definition: vector.f90:333
vectors::vec_slice
class(vecelem) function, dimension(:), allocatable vec_slice(me, lower, upper, stride)
Returns the element array within the requested lower and upper bounds. This is inefficient as it copi...
Definition: vector.f90:420
vectors::elem_back
class(vecelem) function, allocatable elem_back(me)
Returns the last element in the Vector.
Definition: vector.f90:402
vectors::pop_back
class(vecelem) function, allocatable pop_back(me)
Function to extract the last element of the vector.
Definition: vector.f90:578
vectors::invalidvecelem
Invalid Vector element type that is returned in case of an exception.
Definition: vector.f90:68
vectors::assign_vecelem
Interface for the procedure invoked during assignment of VecElem.
Definition: vector.f90:59
vectors::default_newbktsallocated
integer, parameter default_newbktsallocated
Default number of buckets to create on vector capacity increase.
Definition: vector.f90:44
vectors::bkt
Internal Bucket sturcture. Each bucket can contain a number of elements.
Definition: vector.f90:79
vectors::default_bktcap
integer, parameter default_bktcap
Default capacity of internal buckets.
Definition: vector.f90:41
vectors::bktinit
subroutine bktinit(me, status, cap, mold_elem)
Bucket Type Methods.
Definition: vector.f90:929
vectors::destroy
subroutine destroy(me)
Destructor.
Definition: vector.f90:913
vectors::push_back
integer function push_back(me, velem)
Function to add an element at the back of the vector.
Definition: vector.f90:534
vectors::bkt_slice
class(vecelem) function, dimension(:), pointer bkt_slice(me, lower, upper)
Returns a pointer to the Vector slice specified using the user-specified lower and upper bounds....
Definition: vector.f90:483
vectors::bktsliceptr
class(vecelem) function, dimension(:), pointer bktsliceptr(me, start_ind, end_ind)
Definition: vector.f90:988
vectors::elem_insert
subroutine elem_insert(me, pos, NewElems, count)
Inserts the element/elements at the given index and relocate existing elements at the later indices....
Definition: vector.f90:606
vectors::bktsz
pure integer function bktsz(me)
Definition: vector.f90:1019
vectors::reserve
subroutine reserve(me, n)
Increases the capcity of Vector to 'n' if the current capacity is smaller than 'n'.
Definition: vector.f90:310
fmutilbase
FMUTIL Base Module.
Definition: fmutil_base.F90:31
vectors::assignvector
subroutine assignvector(lhs, rhs)
Subroutine for Vector assignment operator.
Definition: vector.f90:883
vectors::bktptr
Pointer to a single bucket.
Definition: vector.f90:106
vectors::bktclear
subroutine bktclear(me)
Definition: vector.f90:964
vectors::is_bktempty
pure logical function is_bktempty(me)
Definition: vector.f90:1008
vectors::capacity
pure integer function capacity(me)
Returns the total number of elements that can be saved in the Vector without any need for increasing ...
Definition: vector.f90:286
vectors::vec_size
pure integer function vec_size(me)
Returns the total number of allocated elements in the Vector.
Definition: vector.f90:268
vectors::elem_at
class(vecelem) function, pointer elem_at(me, Index)
Returns a pointer to the element with the requested index (1-based) Pointer will not be associated in...
Definition: vector.f90:367
vectors
Vector module.
Definition: vector.f90:32