NCEPLIBS-bufr  12.2.0
All Data Structures Namespaces Files Functions Variables Macros Pages
bitmaps.F90
Go to the documentation of this file.
1 
5 
19 subroutine strbtm ( n, lun, ival )
20 
21  use modv_vars, only: mxbtm, mxbtmse
22 
23  use moda_msgcwd
24  use moda_usrint
25  use moda_tables
26  use moda_bitmaps
27 
28  implicit none
29 
30  integer, intent(in) :: n, lun, ival
31  integer node, nodtam, ii, jj, lstjpb
32 
33  logical isbtme
34 
35  node = inv( n, lun )
36 
37  if ( tag(node)(1:5) == 'DPRI ' ) then
38  ! Confirm that this is really an entry within a bitmap. Although it's rare, it is possible for a DPRI element
39  ! to appear in a subset definition outside of a bitmap.
40  isbtme = .false.
41  if ( ntamc > 0 ) then
42  nodtam = lstjpb( node, lun, 'SUB' )
43  do ii = 1, ntamc
44  if ( nodtam == inodtamc(ii) ) then
45  do jj = 1, ntco(ii)
46  if ( ( inodtco(ii,jj) >= inode(lun) ) .and. ( inodtco(ii,jj) <= isc(inode(lun)) ) .and. &
47  ( inodtco(ii,jj) < node ) ) then
48  if ( ctco(ii,jj) == '236000' ) then
49  isbtme = .true.
50  else if ( ( ctco(ii,jj) == '235000' ) .or. ( ctco(ii,jj) == '237255' ) ) then
51  isbtme = .false.
52  end if
53  end if
54  end do
55  end if
56  end do
57  end if
58  if ( .not. isbtme ) then
59  linbtm = .false.
60  return
61  endif
62  if ( .not. linbtm ) then
63  ! This is the start of a new bitmap.
64  if ( nbtm >= mxbtm ) call bort('BUFRLIB: STRBTM - MXBTM OVERFLOW')
65  nbtm = nbtm + 1
66  istbtm(nbtm) = n
67  iszbtm(nbtm) = 0
68  nbtmse(nbtm) = 0
69  linbtm = .true.
70  end if
71  iszbtm(nbtm) = iszbtm(nbtm) + 1
72  if ( ival == 0 ) then
73  ! This is a "set" (value=0) entry in the bitmap.
74  if ( nbtmse(nbtm) >= mxbtmse ) call bort('BUFRLIB: STRBTM - MXBTMSE OVERFLOW')
75  nbtmse(nbtm) = nbtmse(nbtm) + 1
77  end if
78  else if ( itp(node) > 1 ) then
79  linbtm = .false.
80  end if
81 
82  return
83 end subroutine strbtm
84 
109 recursive subroutine gettagre ( lunit, tagi, ntagi, tagre, ntagre, iret )
110 
111  use modv_vars, only: im8b
112 
113  use moda_usrint
114  use moda_msgcwd
115  use moda_tables
116 
117  implicit none
118 
119  integer, intent(in) :: lunit, ntagi
120  integer, intent(out) :: iret, ntagre
121  integer my_lunit, my_ntagi, lun, il, im, ni, nre, ltre, ii
122 
123  character*(*), intent(in) :: tagi
124  character*(*), intent(out) :: tagre
125  character*10 tagtmp
126 
127  ! Check for I8 integers.
128 
129  if(im8b) then
130  im8b=.false.
131  call x84(lunit,my_lunit,1)
132  call x84(ntagi,my_ntagi,1)
133  call gettagre(my_lunit,tagi,my_ntagi,tagre,ntagre,iret)
134  call x48(ntagre,ntagre,1)
135  call x48(iret,iret,1)
136  im8b=.true.
137  return
138  endif
139 
140  iret = -1
141 
142  ! Get lun from lunit.
143 
144  call status( lunit, lun, il, im )
145  if ( il == 0 ) return
146  if ( inode(lun) /= inv(1,lun) ) return
147 
148  ! Get tagre and ntagre from the (ntagi)th occurrence of tagi.
149 
150  call fstag( lun, tagi, ntagi, 1, ni, iret )
151  if ( iret /= 0 ) return
152  nre = nrfelm(ni,lun)
153  if ( nre > 0 ) then
154  iret = 0
155  tagre = tag(inv(nre,lun))
156  call strsuc( tagre, tagtmp, ltre )
157  ntagre = 0
158  do ii = 1, nre
159  if ( tag(inv(ii,lun))(1:ltre) == tagre(1:ltre) ) then
160  ntagre = ntagre + 1
161  end if
162  end do
163  end if
164 
165  return
166 end subroutine gettagre
167 
182 integer function igetrfel ( n, lun ) result ( iret )
183 
184  use moda_msgcwd
185  use moda_usrint
186  use moda_tables
187  use moda_bitmaps
188  use moda_nrv203
189 
190  implicit none
191 
192  integer, intent(in) :: n, lun
193  integer node, ii, jj, nn, idxta, idn, ntc, nodflw, nodl236, nodbmap, nodrfe, nodnn, nodtam, idxbtm, iemrk, iect, &
194  lstjpb, imrkopr
195 
196  character*(*), parameter :: bort_str_mrkopr = &
197  'BUFRLIB: IGETRFEL - UNABLE TO FIND PREVIOUS ELEMENT REFERENCED BY MARKER OPERATOR '
198  character*128 bort_str
199  character*6 cflwopr, adn30, fxy
200  character*1 tab
201 
202  iret = 0
203 
204  node = inv( n, lun )
205 
206  if ( itp(node) > 1 ) then
207  if ( node == lstnod ) then
208  lstnodct = lstnodct + 1
209  else
210  lstnod = node
211  lstnodct = 1
212  end if
213  ! Does this subset definition contain any Table C operators with an X value of 21 or greater?
214  idxta = 0
215  if ( ntamc > 0 ) then
216  nodtam = lstjpb( node, lun, 'SUB' )
217  do ii = 1, ntamc
218  if ( nodtam == inodtamc(ii) ) then
219  idxta = ii
220  ntc = ntco(ii)
221  end if
222  end do
223  end if
224  if ( ( idxta > 0 ) .and. ( nbtm > 0 ) ) then
225  ! Check whether this element references a previous element in the same subset via an internal bitmap. To do this,
226  ! we first need to determine the appropriate "follow" operator (if any) corresponding to this element.
227  cflwopr = 'XXXXXX'
228  if ( imrkopr(tag(node)) == 1 ) then
229  cflwopr = tag(node)(1:3) // '000'
230  else
231  call nemtab( lun, tag(node), idn, tab, nn )
232  if ( tab == 'B' ) then
233  fxy = adn30(idn,6)
234  if ( fxy(2:3) == '33' ) cflwopr = '222000'
235  end if
236  end if
237  if ( cflwopr == 'XXXXXX' ) return
238  ! Now, check whether the appropriate "follow" operator was actually present in the subset. If there are multiple
239  ! occurrences, we want the one that most recently precedes the element in question.
240  nodflw = 0
241  do jj = 1, ntc
242  if ( ( ctco(idxta,jj) == cflwopr ) .and. ( inodtco(idxta,jj) >= inode(lun) ) .and. &
243  ( inodtco(idxta,jj) <= isc(inode(lun)) ) .and. ( inodtco(idxta,jj) < node ) ) nodflw = inodtco(idxta,jj)
244  enddo
245  if ( nodflw == 0 ) then
246  if ( imrkopr(tag(node)) == 1 ) then
247  write(bort_str,'("BUFRLB: IGETRFEL - UNABLE TO FIND FOLLOW OPERATOR ",A," IN SUBSET")') cflwopr
248  call bort(bort_str)
249  endif
250  return
251  end if
252  ! We found an appropriate corresponding "follow" operator, so now we need to look for a bitmap corresponding to
253  ! this operator. First, look for a bitmap indicator.
254  nodl236 = 0
255  nodbmap = 0
256  jj = 1
257  do while ( ( jj <= ntc ) .and. ( inodtco(idxta,jj) >= inode(lun) ) .and. &
258  ( inodtco(idxta,jj) <= isc(inode(lun)) ) .and. ( nodbmap == 0 ) )
259  if ( ctco(idxta,jj) == '236000' ) then
260  nodl236 = inodtco(idxta,jj)
261  if ( inodtco(idxta,jj) == nodflw ) nodbmap = nodflw
262  else if ( ( ctco(idxta,jj) == '235000' ) .or. ( ctco(idxta,jj) == '237255' ) ) then
263  nodl236 = 0
264  else if ( ( ctco(idxta,jj) == '237000' ) .and. ( inodtco(idxta,jj) == nodflw ) .and. ( nodl236 /= 0 ) ) then
265  nodbmap = nodl236
266  end if
267  jj = jj + 1
268  end do
269  if ( nodbmap == 0 ) then
270  ! There was no valid bitmap indicator, so we'll just look for a bitmap after the "follow" indicator.
271  nodbmap = nodflw
272  end if
273  ! Find the corresponding bitmap.
274  nn = 1
275  idxbtm = 0
276  do while ( ( idxbtm == 0 ) .and. ( nn <= nval(lun) ) )
277  if ( inv( nn, lun ) > nodbmap ) then
278  ii = 1
279  do while ( ( idxbtm == 0 ) .and. ( ii <= nbtm ) )
280  if ( nn == istbtm(ii) ) then
281  idxbtm = ii
282  else
283  ii = ii + 1
284  end if
285  end do
286  end if
287  nn = nn + 1
288  end do
289  if ( idxbtm == 0 ) then
290  if ( imrkopr(tag(node)) == 1 ) then
291  write(bort_str,'("BUFRLB: IGETRFEL - UNABLE TO FIND BITMAP FOR MARKER OPERATOR ",A)') tag(node)
292  call bort(bort_str)
293  endif
294  return
295  end if
296  ! Use the bitmap to find the previous element in the subset that is referenced by the current element.
297  ! Search backwards from the start of the bitmap, but make sure not to cross a 2-35-000 operator.
298  if ( lstnodct > nbtmse(idxbtm) ) then
299  if ( imrkopr(tag(node)) == 1 ) call bort( bort_str_mrkopr // tag(node) )
300  return
301  end if
302  iemrk = iszbtm(idxbtm) - ibtmse(idxbtm,lstnodct) + 1
303  iect = 0
304  do while ( ( nn >= 1 ) .and. ( iret == 0 ) )
305  nodnn = inv( nn, lun )
306  if ( nodnn <= nodbmap ) then
307  do jj = 1, ntc
308  if ( ( nodnn == inodtco(idxta,jj) ) .and. ( ctco(idxta,jj) == '235000' ) ) then
309  if ( imrkopr(tag(node)) == 1 ) call bort( bort_str_mrkopr // tag(node) )
310  return
311  end if
312  end do
313  if ( itp(nodnn) > 1 ) then
314  iect = iect + 1
315  if ( iect == iemrk ) iret = nn
316  end if
317  end if
318  nn = nn - 1
319  end do
320  if ( iret == 0 ) then
321  if ( imrkopr(tag(node)) == 1 ) call bort( bort_str_mrkopr // tag(node) )
322  return
323  end if
324  if ( imrkopr(tag(node)) == 1 ) then
325  ! This element is a marker operator, so set the scale, reference value and bit width accordingly based on
326  ! those of the previous referenced element.
327  nodrfe = inv( iret, lun )
328  isc(node) = isc(nodrfe)
329  if ( tag(node)(1:3) == '225' ) then
330  ibt(node) = ibt(nodrfe) + 1
331  irf(node) = -1 * (2 ** ibt(nodrfe))
332  else
333  ibt(node) = ibt(nodrfe)
334  irf(node) = irf(nodrfe)
335  if ( nnrv > 0 ) then
336  do ii = 1, nnrv
337  if ( ( nodrfe /= inodnrv(ii) ) .and. ( tag(nodrfe)(1:8) == tagnrv(ii) ) .and. &
338  ( nodrfe >= isnrv(ii) ) .and. ( nodrfe <= ienrv(ii) ) ) then
339  irf(node) = int(nrv(ii))
340  return
341  end if
342  end do
343  end if
344  end if
345  end if
346  end if
347  end if
348 
349  return
350 end function igetrfel
351 
360 integer function imrkopr(nemo) result(iret)
361 
362  implicit none
363 
364  character*(*), intent(in) :: nemo
365 
366  if (len(nemo)<6) then
367  iret = 0
368  else if ( ( nemo(4:6)=='255' ) .and. &
369  ( ( nemo(1:3)=='223' ) .or. ( nemo(1:3)=='224' ) .or. ( nemo(1:3)=='225' ) .or. ( nemo(1:3)=='232' ) ) ) then
370  iret = 1
371  else
372  iret = 0
373  endif
374 
375  return
376 end function imrkopr
integer function igetrfel(n, lun)
Check whether a subset element refers to a previous element within the same subset via an internal bi...
Definition: bitmaps.F90:183
subroutine strbtm(n, lun, ival)
Store internal information in module moda_bitmaps if the input element is part of a bitmap.
Definition: bitmaps.F90:20
recursive subroutine gettagre(lunit, tagi, ntagi, tagre, ntagre, iret)
Check whether a specified Table B mnemonic references another Table B mnemonic within the same data s...
Definition: bitmaps.F90:110
integer function imrkopr(nemo)
Check whether a specified mnemonic is a Table C marker operator.
Definition: bitmaps.F90:361
subroutine bort(str)
Log an error message, then abort the application program.
Definition: borts.F90:15
subroutine nemtab(lun, nemo, idn, tab, iret)
Get information about a descriptor, based on a mnemonic.
Definition: fxy.F90:434
character *(*) function adn30(idn, ldn)
Convert an FXY value from its WMO bit-wise representation to a character string of length 5 or 6.
Definition: fxy.F90:18
subroutine strsuc(str1, str2, lens)
Remove leading and trailing blanks from a character string.
Definition: misc.F90:199
Declare arrays and variables used to store bitmaps internally within a data subset definition.
integer, dimension(:), allocatable iszbtm
Size of bitmap (total number of entries, whether "set" (set to a value of 0) or not).
integer lstnod
Most recent jump/link table entry that was processed by function igetrfel() and whose corresponding v...
integer, dimension(:,:), allocatable inodtco
Entries within jump/link table which contain Table C operators.
integer ntamc
Number of Table A mnemonics in jump/link table (up to a maximum of mxtamc) which contain at least one...
integer, dimension(:), allocatable istbtm
Ordinal position in data subset definition corresponding to the first entry of the bitmap.
integer nbtm
Number of stored bitmaps for the current data subset (up to a maximum of mxbtm).
integer, dimension(:), allocatable inodtamc
Entries within jump/link table which contain Table A mnemonics.
integer, dimension(:,:), allocatable ibtmse
Ordinal positions in bitmap of bits that were "set" (set to a value of 0); these ordinal positions ca...
integer lstnodct
Current count of consecutive occurrences of lstnod.
logical linbtm
true if a bitmap is in the process of being read for the current data subset; false otherwise.
integer, dimension(:), allocatable nbtmse
Number of "set" entries (set to a value of 0) in the bitmap.
character *6, dimension(:,:), allocatable ctco
Table C operators corresponding to inodtco.
integer, dimension(:), allocatable ntco
Number of Table C operators (with an XX value of 21 or greater) within the data subset definition of ...
Declare arrays used to store information about the current BUFR message that is in the process of bei...
integer, dimension(:), allocatable inode
Table A mnemonic for type of BUFR message.
Declare arrays and variables for use with any 2-03-YYY (change reference value) operators present wit...
integer, dimension(:), allocatable ienrv
End of entry range in jump/link table, within which the corresponding new reference value in nrv will...
character *8, dimension(:), allocatable tagnrv
Table B mnemonic to which the corresponding new reference value in nrv applies.
integer, dimension(:), allocatable isnrv
Start of entry range in jump/link table, within which the corresponding new reference value in nrv wi...
integer nnrv
Number of entries in the jump/link table which contain new reference values (up to a maximum of mxnrv...
integer *8, dimension(:), allocatable nrv
New reference values corresponding to inodnrv.
integer, dimension(:), allocatable inodnrv
Entries within jump/link table which contain new reference values.
Declare arrays and variables used to store the internal jump/link table.
integer, dimension(:), allocatable irf
Reference values corresponding to tag and typ:
integer, dimension(:), allocatable isc
Scale factors corresponding to tag and typ:
integer, dimension(:), allocatable ibt
Bit widths corresponding to tag and typ:
character *10, dimension(:), allocatable tag
Mnemonics in the jump/link table.
integer, dimension(:), allocatable itp
Integer type values corresponding to typ:
Declare arrays used to store data values and associated metadata for the current BUFR data subset in ...
integer, dimension(:), allocatable nval
Number of data values in BUFR data subset.
integer, dimension(:,:), allocatable, target inv
Inventory pointer which links each data value to its corresponding node in the internal jump/link tab...
integer, dimension(:,:), allocatable nrfelm
Referenced data value, for data values which refer to a previous data value in the BUFR data subset v...
recursive subroutine status(lunit, lun, il, im)
Check whether a specified Fortran logical unit number is currently connected to the NCEPLIBS-bufr sof...
subroutine x48(iin4, iout8, nval)
Encode one or more 4-byte integer values as 8-byte integer values.
Definition: x4884.F90:18
subroutine x84(iin8, iout4, nval)
Encode one or more 8-byte integer values as 4-byte integer values.
Definition: x4884.F90:65