48 type,
abstract,
public :: vecelem
54 generic,
public ::
assignment(=) => assignvecelem
62 class(vecelem),
intent(out) :: lhs
63 class(vecelem),
intent(in) :: rhs
72 logical :: invalid = .true.
82 class(vecelem),
dimension(:),
allocatable :: bktdata
84 logical,
dimension(:),
allocatable :: slotfree
107 type(
bkt),
pointer :: pbkt => null()
116 integer,
public :: status = 0
119 logical :: storageallocated = .false.
128 integer :: usedbkts = 0
131 integer :: allocatedbkts = 0
134 class(vecelem),
allocatable :: moldelem
137 type(
bktptr),
dimension(:),
allocatable :: vecdata
231 subroutine initialize(me, NewBktsToAllocate, BktCap, MoldElem)
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
244 if (
present(newbktstoallocate)) me%NewBktsToAllocate = newbktstoallocate
247 if (me%StorageAllocated)
return
249 if (
present(bktcap)) me%BktCap = bktcap
252 if (
present(moldelem))
then
253 allocate(me%MoldElem, source=moldelem)
254 call me%create_newbkts(me%NewBktsToAllocate)
257 if (me%status == 0)
then
258 me%StorageAllocated = .true.
269 class(
vector),
intent(in) :: me
274 if ((.NOT. me%StorageAllocated) .OR. me%UsedBkts == 0)
return
277 vec_size = (me%UsedBkts-1)*me%BktCap &
278 + me%VecData(me%UsedBkts)%pBkt%bktsz()
287 class(
vector),
intent(in) :: me
290 capacity = me%AllocatedBkts*me%BktCap
299 class(
vector),
intent(in) :: me
311 class(
vector),
intent(inout) :: me
313 integer,
intent(in) :: n
321 numbkts = ceiling(fracbkts/me%BktCap) - me%AllocatedBkts
323 if (numbkts > 0)
then
324 call me%create_newbkts(numbkts)
334 class(
vector),
intent(inout) :: me
336 type(
bktptr),
dimension(:),
allocatable :: tmp
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()
345 me%AllocatedBkts = me%UsedBkts
348 if (me%AllocatedBkts < 1)
then
350 me%StorageAllocated = .false.
351 if (
allocated(me%VecData))
deallocate(me%VecData, stat=me%status)
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)
368 class(
vector),
intent(inout) :: me
370 integer,
intent(in) :: index
372 class(vecelem),
pointer :: elem
374 integer :: bktnum, offset
377 call me%Index2Bkt(index, bktnum, offset)
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)
392 class(
vector),
intent(inout) :: me
393 class(vecelem),
allocatable :: elem
395 allocate(elem, source=me%ElemAt(1))
403 class(
vector),
intent(inout) :: me
404 class(vecelem),
allocatable :: elem
407 index = (me%UsedBkts-1)*me%BktCap &
408 + me%VecData(me%UsedBkts)%pBkt%bktsz()
409 allocate(elem, source=me%ElemAt(index))
419 function vec_slice(me, lower, upper, stride)
result(arr)
421 class(
vector),
intent(inout) :: me
424 integer,
intent(in) :: lower
427 integer,
intent(in) :: upper
430 integer,
intent(in),
optional :: stride
432 class(vecelem),
dimension(:),
allocatable :: arr
434 integer :: step, ctr, sz, vecsz
435 integer,
dimension(:),
allocatable :: elemindices
437 if (
present(stride))
then
444 elemindices = [(ctr, ctr = lower, upper, step)]
447 sz =
size(elemindices)
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
457 allocate(arr(sz), mold=me%VecData(1)%pBkt%bktelem(1), &
464 integer ::
bkt, offset
465 call me%Index2Bkt(elemindices(ctr),
bkt, offset)
466 arr(ctr) = me%VecData(
bkt)%pBkt%bktelem(offset)
484 class(
vector),
intent(inout) :: me
487 integer,
intent(in) :: lower
493 integer,
intent(inout) :: upper
495 class(vecelem),
dimension(:),
pointer :: ptr
497 integer :: bktl, offsetl, bktu, offsetu, ub, vecsz, ctr
498 logical :: boundsvalid
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.
509 if (boundsvalid)
then
510 call me%Index2Bkt(lower, bktl, offsetl)
511 call me%Index2Bkt(upper, bktu, offsetu)
513 if (bktl /= bktu)
then
515 if (upper < lower)
then
517 upper = (bktl-1)*me%BktCap + 1
518 ptr => me%VecData(bktl)%pBkt%bktsliceptr(offsetl,1)
521 upper = bktl*me%BktCap
522 ptr => me%VecData(bktl)%pBkt%bktsliceptr(offsetl,me%BktCap)
526 ptr => me%VecData(bktl)%pBkt%bktsliceptr(offsetl,offsetu)
535 class(
vector),
intent(inout) :: me
537 class(vecelem),
intent(in) :: velem
544 if (.NOT. me%StorageAllocated)
then
546 allocate(me%MoldElem, source=velem)
547 call me%create_newbkts(me%NewBktsToAllocate)
548 if (me%status /= 0)
return
554 if (me%AllocatedBkts > 0 .AND. me%UsedBkts < 1) me%UsedBkts = 1
555 offset = me%VecData(me%UsedBkts)%pBkt%bktsz() + 1
558 if (offset > me%BktCap)
then
560 call me%create_newbkts(me%NewBktsToAllocate)
561 if (me%status /= 0)
return
563 me%UsedBkts = me%UsedBkts + 1
568 call me%VecData(me%UsedBkts)%pBkt%add_bktelem(offset, velem)
569 index = offset + (me%UsedBkts-1)*me%BktCap
579 class(
vector),
intent(inout) :: me
580 class(vecelem),
allocatable :: velem
585 bktind = me%vecdata(me%UsedBkts)%pBkt%bktsz()
586 allocate(velem, source=me%VecData(me%UsedBkts)%pBkt%bktelem(bktind))
589 call me%VecData(me%UsedBkts)%pBkt%del_bktelem(bktind)
592 if (me%vecdata(me%UsedBkts)%pBkt%is_bktempty())
then
593 me%UsedBkts = me%UsedBkts - 1
607 class(
vector),
intent(inout) :: me
610 integer,
intent(in) :: pos
612 class(vecelem),
dimension(:),
intent(in) :: NewElems
616 integer,
intent(in),
optional :: count
618 integer :: countval, reqdslots, emptyslots, newbkts, ctr, sz, vecsz
619 integer :: Bkt0, Offset0, Bkt1, Offset1, ctr1, ctr2
623 if (
present(count)) countval = count
631 if (.NOT. me%StorageAllocated)
then
633 allocate(me%MoldElem, source=newelems(1))
634 call me%create_newbkts(me%NewBktsToAllocate)
635 if (me%status /= 0)
return
641 if (pos < 1 .OR. countval < 1 .OR. ((pos-vecsz) > 1))
then
647 reqdslots = countval*sz
648 emptyslots = me%Capacity() - me%Size()
649 tmp = reqdslots - emptyslots
650 newbkts = ceiling(tmp/me%BktCap)
652 if (newbkts > 0)
then
654 call me%create_newbkts(newbkts)
658 call me%Index2Bkt(pos, bkt0, offset0)
660 call me%Index2Bkt(pos+countval*sz, bkt1, offset1)
663 reqdslots = me%Size() - pos + 1
666 do ctr = 1, reqdslots
669 call me%VecData(bkt1)%pBkt%add_bktelem(offset1, &
670 me%VecData(bkt0)%pBkt%bktelem(offset0))
672 call me%VecData(bkt0)%pBkt%del_bktelem(offset0)
675 offset0 = offset0 + 1
676 offset1 = offset1 + 1
677 if (offset0 > me%BktCap)
then
681 if (offset1 > me%BktCap)
then
691 do ctr = 1, countval*sz
693 call me%VecData(bkt0)%pBkt%add_bktelem(offset0, newelems(ctr1))
696 if (ctr1 > sz) ctr1 = 1
697 offset0 = offset0 + 1
698 if (offset0 > me%BktCap)
then
705 me%UsedBkts = me%usedBkts + newbkts
718 class(
vector),
intent(inout) :: me
720 integer,
intent(In) :: lower
724 integer,
intent(In),
optional :: upper
726 integer :: sz, ctr, upperval
727 integer :: Bkt0, Offset0, Bkt1, Offset1
731 if (lower < 1 .OR. lower > sz .OR. sz < 1)
return
733 if (
present(upper))
then
734 if (lower > upper)
return
738 call me%Index2Bkt(lower, bkt0, offset0)
741 if (
present(upper))
then
743 call me%Index2Bkt(upperval, bkt1, offset1)
747 offset1 = offset0 + 1
748 if (offset1 > me%BktCap)
then
755 do ctr = 1, (sz - upperval + 1)
757 call me%VecData(bkt0)%pBkt%add_bktelem(offset0, &
758 me%VecData(bkt1)%pBkt%bktelem(offset1))
761 offset0 = offset0 + 1
762 offset1 = offset1 + 1
763 if (offset0 > me%BktCap)
then
767 if (offset1 > me%BktCap)
then
774 if (offset0 /= 1)
then
775 do ctr = offset0, me%BktCap
776 call me%VecData(bkt0)%pBkt%del_bktelem(ctr)
782 call me%VecData(ctr)%pBkt%bktclear()
785 me%UsedBkts = bkt0 - 1
795 class(
vector),
intent(inout) :: me
799 do ctr = 1, me%UsedBkts
800 call me%VecData(ctr)%pBkt%bktclear()
812 class(
vector),
intent(inout) :: me
814 integer,
intent(in) :: NumBkts
816 type(
bktptr),
dimension(:),
allocatable :: tmp
820 allocate(tmp(me%AllocatedBkts+numbkts), stat=me%status)
822 if (me%status == 0)
then
824 if (me%StorageAllocated)
then
826 tmp(1:me%AllocatedBkts) = me%VecData
830 call move_alloc(from=tmp, to=me%VecData)
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
841 if (ctr > numbkts)
then
842 me%AllocatedBkts = me%AllocatedBkts + ctr - 1
843 me%StorageAllocated = .true.
855 class(
vector),
intent(in) :: me
857 integer,
intent(in) :: index
858 integer,
intent(out) ::
bkt
859 integer,
intent(out) :: bktoffset
865 frac = frac/me%BktCap
869 bktoffset = index - (
bkt-1)*me%BktCap
877 class(vecelem),
intent(in) :: rhs
884 class(
vector),
intent(out) :: lhs
885 class(
vector),
intent(in) :: rhs
892 allocate(lhs%VecData(
size(rhs%VecData)))
895 allocate(lhs%MoldElem, source=rhs%MoldElem)
896 do ctr = 1, rhs%AllocatedBkts
897 allocate(lhs%VecData(ctr)%pBkt, source=rhs%VecData(ctr)%pBkt)
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
914 type(
vector),
intent(inout) :: me
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()
928 subroutine bktinit(me, status, cap, mold_elem)
930 class(
bkt),
intent(inout) :: me
931 integer,
intent(out) :: status
932 integer,
intent(in) :: cap
933 class(vecelem),
intent(in) :: mold_elem
935 allocate(me%SlotFree(cap), stat=status)
936 allocate(me%BktData(cap), stat=status, mold=mold_elem)
944 class(
bkt),
intent(inout) :: me
945 integer,
intent(in) :: offset
946 class(vecelem),
intent(in) :: elem
948 me%BktData(offset) = elem
949 me%SlotFree(offset) = .false.
956 class(
bkt),
intent(inout) :: me
957 integer,
intent(in) :: offset
959 me%SlotFree(offset) = .true.
965 class(
bkt),
intent(inout) :: me
974 class(
bkt),
intent(in),
target :: me
975 integer,
intent(in) :: offset
976 class(vecelem),
pointer ::
bktelem
978 if (.NOT. me%SlotFree(offset))
then
989 class(
bkt),
intent(in),
target :: me
990 integer,
intent(in) :: start_ind, end_ind
991 class(vecelem),
dimension(:),
pointer ::
bktsliceptr
998 if (start_ind > end_ind) stride = -1
1000 if (any(me%SlotFree(start_ind:end_ind:stride)))
return
1002 bktsliceptr => me%BktData(start_ind:end_ind:stride)
1009 class(
bkt),
intent(in) :: me
1020 class(
bkt),
intent(in) :: me
1022 bktsz = count(.NOT. me%SlotFree)