PartMC  2.6.1
integer_varray.F90
Go to the documentation of this file.
1 ! Copyright (C) 2011-2012 Matthew West
2 ! Licensed under the GNU General Public License version 2 or (at your
3 ! option) any later version. See the file COPYING for details.
4 
5 !> \file
6 !> The pmc_integer_varray module.
7 
8 !> The integer_varray_t structure and assocated subroutines.
10 
11  use pmc_util
12  use pmc_mpi
13 
14  !> A variable-length 1D array of integers.
15  !!
16  !! The number of currently used entries in \c n_entry will generally
17  !! be less than the allocated storage.
19  !> Number of currently used entries.
20  integer :: n_entry
21  !> Array of integer values.
22  integer, allocatable :: entry(:)
23  end type integer_varray_t
24 
25 contains
26 
27 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
28 
29  !> Return the current number of entries.
30  elemental integer function integer_varray_n_entry(integer_varray)
31 
32  !> Array.
33  type(integer_varray_t), intent(in) :: integer_varray
34 
35  if (allocated(integer_varray%entry)) then
36  integer_varray_n_entry = integer_varray%n_entry
37  else
39  end if
40 
41  end function integer_varray_n_entry
42 
43 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
44 
45  !> Changes the given integer_varray to exactly the given new_length.
46  !!
47  !! This function should not be called directly, but rather use
48  !! integer_varray_enlarge(), integer_varray_shrink().
49  subroutine integer_varray_realloc(integer_varray, new_length)
50 
51  !> Array to reallocate.
52  type(integer_varray_t), intent(inout) :: integer_varray
53  !> New length of the array.
54  integer, intent(in) :: new_length
55 
56  integer, allocatable :: new_entries(:)
57 
58  if (.not. allocated(integer_varray%entry)) then
59  allocate(integer_varray%entry(new_length))
60  integer_varray%n_entry = 0
61  return
62  end if
63 
64  call assert(479324776, new_length >= integer_varray%n_entry)
65  allocate(new_entries(new_length))
66  new_entries(:integer_varray%n_entry) &
67  = integer_varray%entry(1:integer_varray%n_entry)
68  call move_alloc(new_entries, integer_varray%entry)
69 
70  end subroutine integer_varray_realloc
71 
72 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
73 
74  !> Resets an integer_varray to have zero entries.
75  elemental subroutine integer_varray_zero(integer_varray)
76 
77  !> Structure to zero.
78  type(integer_varray_t), intent(inout) :: integer_varray
79 
80  integer_varray%n_entry = 0
81  if (allocated(integer_varray%entry)) then
82  deallocate(integer_varray%entry)
83  end if
84 
85  end subroutine integer_varray_zero
86 
87 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
88 
89  !> Enlarges the given array so that it is at least of size n.
90  subroutine integer_varray_enlarge(integer_varray, n)
91 
92  !> Array to enlarge.
93  type(integer_varray_t), intent(inout) :: integer_varray
94  !> Minimum new size of array.
95  integer, intent(in) :: n
96 
97  if (.not. allocated(integer_varray%entry)) then
98  call integer_varray_realloc(integer_varray, pow2_above(n))
99  return
100  end if
101 
102  if (n <= size(integer_varray%entry)) return
103 
104  call integer_varray_realloc(integer_varray, pow2_above(n))
105 
106  end subroutine integer_varray_enlarge
107 
108 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
109 
110  !> Possibly shrinks the storage of the given array, ensuring that
111  !> it can still store the used entries.
112  subroutine integer_varray_shrink(integer_varray)
113 
114  !> Array to shrink.
115  type(integer_varray_t), intent(inout) :: integer_varray
116 
117  integer :: length, new_length
118 
119  if (.not. allocated(integer_varray%entry)) return
120 
121  new_length = pow2_above(integer_varray%n_entry)
122  if (new_length < size(integer_varray%entry)) then
123  call integer_varray_realloc(integer_varray, new_length)
124  end if
125 
126  end subroutine integer_varray_shrink
127 
128 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
129 
130  !> Adds the given number to the end of the array.
131  subroutine integer_varray_append(integer_varray, val)
132 
133  !> Array to add to.
134  type(integer_varray_t), intent(inout) :: integer_varray
135  !> Value to add.
136  integer, intent(in) :: val
137 
138  integer :: n
139 
140  n = integer_varray%n_entry + 1
141  call integer_varray_enlarge(integer_varray, n)
142  integer_varray%entry(n) = val
143  integer_varray%n_entry = n
144 
145  end subroutine integer_varray_append
146 
147 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
148 
149  !> Removes the entry at the given index, repacking values to
150  !> maintain contiguous data.
151  subroutine integer_varray_remove_entry(integer_varray, index)
152 
153  !> Array to remove from.
154  type(integer_varray_t), intent(inout) :: integer_varray
155  !> Index of entry to remove.
156  integer, intent(in) :: index
157 
158  call assert(302759108, allocated(integer_varray%entry))
159  call assert(541032660, index >= 1)
160  call assert(385739765, index <= integer_varray%n_entry)
161  if (index < integer_varray%n_entry) then
162  ! shift last entry into now-empty slot to preserve dense packing
163  integer_varray%entry(index) &
164  = integer_varray%entry(integer_varray%n_entry)
165  end if
166  ! clear now-unused last entry for safety
167  integer_varray%entry(integer_varray%n_entry) = 0
168  integer_varray%n_entry = integer_varray%n_entry - 1
169  call integer_varray_shrink(integer_varray)
170 
171  end subroutine integer_varray_remove_entry
172 
173 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
174 
175  !> Determines the number of bytes required to pack the given value.
176  integer function pmc_mpi_pack_size_integer_varray(val)
177 
178  !> Value to pack.
179  type(integer_varray_t), intent(in) :: val
180 
181  logical :: is_allocated
182  integer, allocatable :: tmp_entry(:)
183  integer :: total_size
184 
185  is_allocated = allocated(val%entry)
186  total_size = pmc_mpi_pack_size_logical(is_allocated)
187  if (is_allocated) then
188  tmp_entry = val%entry(1:val%n_entry)
189  total_size = total_size &
191  end if
193 
195 
196 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
197 
198  !> Packs the given value into the buffer, advancing position.
199  subroutine pmc_mpi_pack_integer_varray(buffer, position, val)
200 
201  !> Memory buffer.
202  character, intent(inout) :: buffer(:)
203  !> Current buffer position.
204  integer, intent(inout) :: position
205  !> Value to pack.
206  type(integer_varray_t), intent(in) :: val
207 
208 #ifdef PMC_USE_MPI
209  logical :: is_allocated
210  integer :: prev_position
211  integer, allocatable :: tmp_entry(:)
212 
213  prev_position = position
214  is_allocated = allocated(val%entry)
215  call pmc_mpi_pack_logical(buffer, position, is_allocated)
216  if (is_allocated) then
217  tmp_entry = val%entry(1:val%n_entry)
218  call pmc_mpi_pack_integer_array(buffer, position, tmp_entry)
219  end if
220  call assert(230655880, &
221  position - prev_position <= pmc_mpi_pack_size_integer_varray(val))
222 #endif
223 
224  end subroutine pmc_mpi_pack_integer_varray
225 
226 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
227 
228  !> Unpacks the given value from the buffer, advancing position.
229  subroutine pmc_mpi_unpack_integer_varray(buffer, position, val)
230 
231  !> Memory buffer.
232  character, intent(inout) :: buffer(:)
233  !> Current buffer position.
234  integer, intent(inout) :: position
235  !> Value to pack.
236  type(integer_varray_t), intent(inout) :: val
237 
238 #ifdef PMC_USE_MPI
239  integer :: prev_position
240  logical :: is_allocated
241  integer, allocatable :: tmp_entry(:)
242 
243  prev_position = position
244  call pmc_mpi_unpack_logical(buffer, position, is_allocated)
245  if (is_allocated) then
246  call pmc_mpi_unpack_integer_array(buffer, position, tmp_entry)
247  call integer_varray_realloc(val, size(tmp_entry))
248  val%entry(1:size(tmp_entry)) = tmp_entry
249  else
250  if (allocated(val%entry)) then
251  deallocate(val%entry)
252  end if
253  end if
254  call assert(355866103, &
255  position - prev_position <= pmc_mpi_pack_size_integer_varray(val))
256 #endif
257 
258  end subroutine pmc_mpi_unpack_integer_varray
259 
260 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
261 
262 end module pmc_integer_varray
pmc_mpi
Wrapper functions for MPI.
Definition: mpi.F90:13
pmc_integer_varray::integer_varray_zero
elemental subroutine integer_varray_zero(integer_varray)
Resets an integer_varray to have zero entries.
Definition: integer_varray.F90:76
pmc_mpi::pmc_mpi_unpack_integer_array
subroutine pmc_mpi_unpack_integer_array(buffer, position, val)
Unpacks the given value from the buffer, advancing position.
Definition: mpi.F90:946
pmc_mpi::pmc_mpi_pack_integer_array
subroutine pmc_mpi_pack_integer_array(buffer, position, val)
Packs the given value into the buffer, advancing position.
Definition: mpi.F90:688
pmc_mpi::pmc_mpi_pack_logical
subroutine pmc_mpi_pack_logical(buffer, position, val)
Packs the given value into the buffer, advancing position.
Definition: mpi.F90:638
pmc_util::pow2_above
integer function pow2_above(n)
Return the least power-of-2 that is at least equal to n.
Definition: util.F90:1642
pmc_util::assert
subroutine assert(code, condition_ok)
Errors unless condition_ok is true.
Definition: util.F90:103
pmc_integer_varray::pmc_mpi_pack_size_integer_varray
integer function pmc_mpi_pack_size_integer_varray(val)
Determines the number of bytes required to pack the given value.
Definition: integer_varray.F90:177
pmc_integer_varray::integer_varray_n_entry
elemental integer function integer_varray_n_entry(integer_varray)
Return the current number of entries.
Definition: integer_varray.F90:31
pmc_mpi::pmc_mpi_pack_size_logical
integer function pmc_mpi_pack_size_logical(val)
Determines the number of bytes required to pack the given value.
Definition: mpi.F90:407
pmc_integer_varray
The integer_varray_t structure and assocated subroutines.
Definition: integer_varray.F90:9
pmc_integer_varray::integer_varray_shrink
subroutine integer_varray_shrink(integer_varray)
Possibly shrinks the storage of the given array, ensuring that it can still store the used entries.
Definition: integer_varray.F90:113
pmc_integer_varray::integer_varray_t
A variable-length 1D array of integers.
Definition: integer_varray.F90:18
pmc_integer_varray::integer_varray_remove_entry
subroutine integer_varray_remove_entry(integer_varray, index)
Removes the entry at the given index, repacking values to maintain contiguous data.
Definition: integer_varray.F90:152
pmc_integer_varray::pmc_mpi_pack_integer_varray
subroutine pmc_mpi_pack_integer_varray(buffer, position, val)
Packs the given value into the buffer, advancing position.
Definition: integer_varray.F90:200
pmc_integer_varray::integer_varray_realloc
subroutine integer_varray_realloc(integer_varray, new_length)
Changes the given integer_varray to exactly the given new_length.
Definition: integer_varray.F90:50
pmc_mpi::pmc_mpi_unpack_logical
subroutine pmc_mpi_unpack_logical(buffer, position, val)
Unpacks the given value from the buffer, advancing position.
Definition: mpi.F90:896
pmc_integer_varray::pmc_mpi_unpack_integer_varray
subroutine pmc_mpi_unpack_integer_varray(buffer, position, val)
Unpacks the given value from the buffer, advancing position.
Definition: integer_varray.F90:230
pmc_integer_varray::integer_varray_enlarge
subroutine integer_varray_enlarge(integer_varray, n)
Enlarges the given array so that it is at least of size n.
Definition: integer_varray.F90:91
pmc_mpi::pmc_mpi_pack_size_integer_array
integer function pmc_mpi_pack_size_integer_array(val)
Determines the number of bytes required to pack the given value.
Definition: mpi.F90:447
pmc_util
Common utility subroutines.
Definition: util.F90:9
pmc_integer_varray::integer_varray_append
subroutine integer_varray_append(integer_varray, val)
Adds the given number to the end of the array.
Definition: integer_varray.F90:132