NCEPLIBS-bufr  12.3.0
compress.F90
Go to the documentation of this file.
1 
5 
32 recursive subroutine cmpmsg(cf)
33 
34  use bufrlib
35 
36  use moda_msgcmp
37 
38  implicit none
39 
40  integer bort_target_set
41 
42  character, intent(in) :: cf
43  character*128 bort_str
44  character my_cf
45 
46  ! If we're catching bort errors, set a target return location if one doesn't already exist.
47 
48  if (bort_target_set() == 1) then
49  call catch_bort_cmpmsg_c(cf)
51  return
52  endif
53 
54  my_cf = cf
55  call capit(my_cf)
56  if(my_cf /= 'Y' .and. my_cf /= 'N') then
57  write(bort_str,'("BUFRLIB: CMPMSG - INPUT ARGUMENT IS ",A1,", IT MUST BE EITHER Y, y, N OR n")') cf
58  call bort(bort_str)
59  endif
60  ccmf = my_cf
61 
62  return
63 end subroutine cmpmsg
64 
85 recursive subroutine writcp(lunit)
86 
87  use modv_vars, only: im8b
88 
89  implicit none
90 
91  integer, intent(in) :: lunit
92  integer my_lunit
93 
94  ! Check for I8 integers.
95 
96  if(im8b) then
97  im8b=.false.
98  call x84(lunit,my_lunit,1)
99  call writcp(my_lunit)
100  im8b=.true.
101  return
102  endif
103 
104  call cmpmsg('Y')
105  call writsb(lunit)
106  call cmpmsg('N')
107 
108  return
109 end subroutine writcp
110 
121 subroutine rdcmps(lun)
122 
123  use modv_vars, only: bmiss, mxrst
124 
125  use moda_usrint
126  use moda_msgcwd
127  use moda_bitbuf
128  use moda_tables
129  use moda_rlccmn
130  use moda_stcode
131 
132  implicit none
133 
134  integer, intent(in) :: lun
135  integer*8 :: ival, lref, ninc, lps
136  integer nsbs, jbit, lbit, nbit, n, node, ityp, linc, lre4, nin4, nbmp, nchr, lelm, ibsv, igetrfel, ibfms, icbfms
137 
138  real*8 rval, ups
139 
140  character*128 bort_str
141  character*8 cref, cval
142 
143  equivalence(cval,rval)
144 
145  ! Statement function to compute BUFR "missing value" for field of length lbit bits (all bits "on")
146  lps(lbit) = max(2_8**(lbit)-1,1)
147 
148  ! Setup the subset template
149 
150  call usrtpl(lun,1,1)
151 
152  ! Uncompress a subset into the val array according to Table B
153 
154  nsbs = nsub(lun)
155 
156  ! Note that we are going to unpack the (nsbs)th subset from within the current BUFR message.
157 
158  ibit = mbyt(lun)
159  nrst = 0
160 
161  ! Loop through each element of the subset, including immediately resolving any replication sequences by emulating recursion
162  ! via an explicit goto statement.
163 
164  n = 0
165  11 do n=n+1,nval(lun)
166  node = inv(n,lun)
167  nrfelm(n,lun) = igetrfel(n,lun)
168  nbit = ibt(node)
169  ityp = itp(node)
170 
171  ! In each of the following code blocks, the "local reference value" for the element is determined first, followed by the
172  ! 6-bit value which indicates how many bits are used to store the increment (i.e. offset) from this "local reference value".
173  ! Then, we jump ahead to where this increment is stored for this particular subset, unpack it, and add it to the
174  ! "local reference value" to determine the final uncompressed value for this element from this subset. Note that, if an
175  ! element has the same final uncompressed value for each subset in the message, then the encoding rules for BUFR compression
176  ! dictate that the "local reference value" will be equal to this value, the 6-bit increment length indicator will have a
177  ! value of zero, and the actual increments themselves will be omitted from the message.
178 
179  if(ityp==1.or.ityp==2) then
180  ! This is a numeric element.
181  if(nbit<=32) then
182  call upb(lre4,nbit,mbay(1,lun),ibit)
183  call upb(linc,6,mbay(1,lun),ibit)
184  jbit = ibit + linc*(nsbs-1)
185  call upb(nin4,linc,mbay(1,lun),jbit)
186  lref = lre4
187  ninc = nin4
188  elseif(nbit<=64) then
189  call up8(lref,nbit,mbay(1,lun),ibit)
190  call upb(linc,6,mbay(1,lun),ibit)
191  jbit = ibit + linc*(nsbs-1)
192  call up8(ninc,linc,mbay(1,lun),jbit)
193  endif
194  if(ninc==lps(linc)) then
195  ival = lps(nbit)
196  else
197  ival = lref + ninc
198  endif
199  if(ityp==1) then
200  nbmp = int(ival)
201  call usrtpl(lun,n,nbmp)
202  if (iscodes(lun) /= 0) return
203  goto 11
204  endif
205  if(ival<lps(nbit)) val(n,lun) = ups(ival,node)
206  call strbtm(n,lun,ibfms(val(n,lun)))
207  ibit = ibit + linc*msub(lun)
208  elseif(ityp==3) then
209  ! This is a character element. If there are more than 8 characters, then only the first 8 will be unpacked by this
210  ! routine, and a separate subsequent call to subroutine readlc() will be required to unpack the remainder of the string.
211  ! In this case, pointers will be saved within module @ref moda_rlccmn for later use within readlc().
212  lelm = nbit/8
213  nchr = min(8,lelm)
214  ibsv = ibit
215  cref = ' '
216  call upc(cref,nchr,mbay(1,lun),ibit,.true.)
217  if(lelm>8) then
218  ibit = ibit + (lelm-8)*8
219  nrst = nrst + 1
220  if(nrst>mxrst) then
221  write(bort_str,'("BUFRLIB: RDCMPS - NUMBER OF LONG CHARACTER STRINGS EXCEEDS THE LIMIT (",I4,")")') mxrst
222  call bort(bort_str)
223  endif
224  crtag(nrst) = tag(node)
225  endif
226  ! Unpack the increment length indicator. For character elements, this length is in bytes rather than bits.
227  call upb(linc,6,mbay(1,lun),ibit)
228  if(linc==0) then
229  if(lelm>8) then
230  irnch(nrst) = lelm
231  irbit(nrst) = ibsv
232  endif
233  cval = cref
234  else
235  jbit = ibit + linc*(nsbs-1)*8
236  if(lelm>8) then
237  irnch(nrst) = linc
238  irbit(nrst) = jbit
239  endif
240  nchr = min(8,linc)
241  cval = ' '
242  call upc(cval,nchr,mbay(1,lun),jbit,.true.)
243  endif
244  if (lelm<=8 .and. icbfms(cval,nchr)/=0) then
245  val(n,lun) = bmiss
246  else
247  val(n,lun) = rval
248  endif
249  ibit = ibit + 8*linc*msub(lun)
250  endif
251  enddo
252 
253  return
254 end subroutine rdcmps
255 
270 subroutine cmsgini(lun,mesg,subset,idate,nsub,nbyt)
271 
272  use modv_vars, only: mtv, nby1, nby5, bmostr
273 
274  implicit none
275 
276  integer, intent(in) :: lun, idate, nsub
277  integer, intent(inout) :: nbyt
278  integer, intent(out) :: mesg(*)
279  integer mtyp, msbt, inod, isub, iret, jdate, mcen, mear, mmon, mday, mour, mmin, mbit, mbyt, len3, i4dy
280 
281  character*128 bort_str
282  character*8, intent(in) :: subset
283  character tab
284 
285  ! Get the message tag and type, and break up the date which can be either YYMMDDHH or YYYYMMDDHH
286 
287  call nemtba(lun,subset,mtyp,msbt,inod)
288  call nemtab(lun,subset,isub,tab,iret)
289  if(iret==0) then
290  write(bort_str,'("BUFRLIB: CMSGINI - TABLE A MESSAGE TYPE MNEMONIC ",A," NOT FOUND IN INTERNAL TABLE D ARRAYS")') subset
291  call bort(bort_str)
292  endif
293 
294  jdate = i4dy(idate)
295  mcen = mod(jdate/10**8,100)+1
296  mear = mod(jdate/10**6,100)
297  mmon = mod(jdate/10**4,100)
298  mday = mod(jdate/10**2,100)
299  mour = mod(jdate ,100)
300  mmin = 0
301 
302  if(mear==0) then
303  mcen = mcen-1
304  mear = 100
305  endif
306 
307  ! Initialize the message
308 
309  mbit = 0
310 
311  ! Section 0
312 
313  call pkc(bmostr, 4 , mesg,mbit)
314  ! Note that the actual Section 0 length will be computed and stored below; for now, we're really only interested in
315  ! advancing mbit by the correct amount, so we'll just store a default value of 0.
316  call pkb( 0 , 24 , mesg,mbit)
317  call pkb( 3 , 8 , mesg,mbit)
318 
319  ! Section 1
320 
321  call pkb(nby1 , 24 , mesg,mbit)
322  call pkb( 0 , 8 , mesg,mbit)
323  call pkb( 3 , 8 , mesg,mbit)
324  call pkb( 7 , 8 , mesg,mbit)
325  call pkb( 0 , 8 , mesg,mbit)
326  call pkb( 0 , 8 , mesg,mbit)
327  call pkb(mtyp , 8 , mesg,mbit)
328  call pkb(msbt , 8 , mesg,mbit)
329  call pkb( mtv , 8 , mesg,mbit)
330  call pkb( 0 , 8 , mesg,mbit)
331  call pkb(mear , 8 , mesg,mbit)
332  call pkb(mmon , 8 , mesg,mbit)
333  call pkb(mday , 8 , mesg,mbit)
334  call pkb(mour , 8 , mesg,mbit)
335  call pkb(mmin , 8 , mesg,mbit)
336  call pkb(mcen , 8 , mesg,mbit)
337 
338  ! Section 3
339 
340  len3 = 10
341 
342  call pkb(len3 , 24 , mesg,mbit)
343  call pkb( 0 , 8 , mesg,mbit)
344  call pkb(nsub , 16 , mesg,mbit)
345  call pkb( 192 , 8 , mesg,mbit)
346  call pkb(isub , 16 , mesg,mbit)
347  call pkb( 0 , 8 , mesg,mbit)
348 
349  ! Section 4
350 
351  ! Store the total length of Section 4. Remember that the input value of nbyt only contains the length of the compressed
352  ! data portion of Section 4, so we need to add four bytes to this number in order to account for the total length of
353  ! Section 4. The actual compressed data portion will be filled in later by subroutine wrcmps().
354  call pkb((nbyt+4) , 24 , mesg,mbit)
355  call pkb( 0 , 8 , mesg,mbit)
356 
357  ! Section 5
358 
359  ! This section will be filled in later by subroutine wrcmps(). However, for now, and noting that mbit currently points
360  ! to the last bit of the fourth byte of Section 4, then we have:
361  ! (total length of BUFR message (in Section 0)) =
362  ! (length of message up through fourth byte of Section 4)
363  ! + (length of compressed data portion of Section 4)
364  ! + (length of Section 5)
365  mbyt = mbit/8 + nbyt + nby5
366 
367  ! For output, make nbyt point to the current location of mbit, which is the byte after which to actually begin writing the
368  ! compressed data into Section 4.
369  nbyt = mbit/8
370 
371  ! Now, store the total length of the BUFR message in Section 0.
372  mbit = 32
373  call pkb(mbyt,24,mesg,mbit)
374 
375  return
376 end subroutine cmsgini
377 
395 subroutine wrcmps(lunix)
396 
397  use modv_vars, only: mxcdv, mxcsb, nby5, bmcstr
398 
399  use moda_usrint
400  use moda_msgcwd
401  use moda_bitbuf
402  use moda_mgwa
403  use moda_tables
404  use moda_comprx
405  use moda_comprs
406  use moda_s01cm
407 
408  implicit none
409 
410  integer, intent(in) :: lunix
411  integer ibyt, jbit, lunit, lun, il, im, icol, i, j, node, lbyt, nbyt, nchr, ldata, iupbs01, imrkopr
412 
413  character*128 bort_str
414  character*8 subset
415  character czero
416 
417  logical first, kmiss, edge4, msgfull, cmpres
418 
419  real, parameter :: rln2 = 1./log(2.)
420  real range
421 
422  data first /.true./
423 
424  save first, ibyt, jbit, subset, edge4
425 
426  ! Get the unit and subset tag
427 
428  lunit = abs(lunix)
429  call status(lunit,lun,il,im)
430 
431  do while (.true.)
432 
433  if(first) then
434  ! Initialize some values in order to prepare for the creation of a new compressed BUFR message for output.
435  kbyt = 0
436  ncol = 0
437  lunc = lun
438  nrow = nval(lun)
439  subset = tag(inode(lun))(1:8)
440  first = .false.
441  flush = .false.
442  writ1 = .false.
443  ! The following call to cmsgini() is just being done to determine how many bytes (kbyt) will be taken up in a message
444  ! by the information in Sections 0, 1, 2 and 3. This in turn will allow us to determine how many compressed data subsets
445  ! will fit into Section 4 without overflowing maxbyt. Then, later on, another separate call to cmsgini() will be done to
446  ! actually initialize Sections 0, 1, 2 and 3 of the final compressed BUFR message that will be written out.
447  call cmsgini(lun,mbay(1,lun),subset,idate(lun),ncol,kbyt)
448  ! Check the edition number of the BUFR message to be created
449  edge4 = .false.
450  if(ns01v>0) then
451  i = 1
452  do while ( (.not.edge4) .and. (i<=ns01v) )
453  if( (cmnem(i)=='BEN') .and. (ivmnem(i)>=4) ) then
454  edge4 = .true.
455  else
456  i = i+1
457  endif
458  enddo
459  endif
460  endif
461 
462  if(lun/=lunc) then
463  write(bort_str,.NE.'("BUFRLIB: WRCMPS - FILE ID FOR THIS CALL (",I3,") FILE ID FOR INITIAL CALL (",I3,")'// &
464  ' - UNIT NUMBER NOW IS",I4)') lun,lunc,lunix
465  call bort(bort_str)
466  endif
467 
468  cmpres = .true.
469  if(lunix<0) then
470  ! This is a "flush" call, so clear out the buffer (note that there is no current subset to be stored!) and prepare
471  ! to write the final compressed BUFR message.
472  if(ncol<=0) return
473  flush = .true.
474  writ1 = .true.
475  icol = 1
476  elseif(ncol+1>mxcsb) then
477  ! There's no more room in the internal compression arrays for another subset, so we'll need to write out a message
478  ! containing all of the data in those arrays, then initialize a new message to hold the current subset.
479  cmpres = .false.
480  else
481  ! Check on some other possibly problematic situations
482  if(nval(lun)/=nrow) then
483  writ1 = .true.
484  icol = 1
485  elseif(nval(lun)>mxcdv) then
486  write(bort_str,'("BUFRLIB: WRCMPS - NO. OF ELEMENTS IN THE '// &
487  .GT.'SUBSET (",I6,") THE NO. OF ROWS ALLOCATED FOR THE COMPRESSION MATRIX (",I6,")")') nval(lun),mxcdv
488  call bort(bort_str)
489  elseif(ncol>0) then
490  ! Confirm that all of the nodes are the same as in the previous subset for this same BUFR message. If not, then
491  ! there may be different nested replication sequences activated in the current subset vs. in the previous subset,
492  ! even though the total number of nodes is the same.
493  do i = 1, nval(lun)
494  if ( inv(i,lun) /= jlnode(i) ) then
495  writ1 = .true.
496  icol = 1
497  exit
498  endif
499  enddo
500  endif
501  if(.not.writ1) then
502  ! Store the next subset for compression
503  ncol = ncol+1
504  icol = ncol
505  ibit = 16
506  do i=1,nval(lun)
507  node = inv(i,lun)
508  jlnode(i) = node
509  ityp(i) = itp(node)
510  if(imrkopr(tag(node))==1) then
511  iwid(i) = ibt(inv(nrfelm(i,lun),lun))
512  else
513  iwid(i) = ibt(node)
514  endif
515  if(ityp(i)==1.or.ityp(i)==2) then
516  call up8(matx(i,ncol),iwid(i),ibay,ibit)
517  elseif(ityp(i)==3) then
518  catx(i,ncol) = ' '
519  call upc(catx(i,ncol),iwid(i)/8,ibay,ibit,.true.)
520  endif
521  enddo
522  endif
523  endif
524 
525  ! Will the next subset fit into the current message? The only way to find out is to actually re-do the compression
526  ! by re-computing all of the local reference values, increments, etc. to determine the new Section 4 length.
527 
528  do while (cmpres)
529  if(ncol<=0) then
530  write(bort_str,'("BUFRLIB: WRCMPS - NO. OF COLUMNS CALCULATED '// &
531  .LE.'FOR COMPRESSION MAXRIX IS 0 (=",I6,")")') ncol
532  call bort(bort_str)
533  endif
534  ! ldata will hold the length (in bits) of the compressed data, i.e. the sum total for all data values for all data
535  ! subsets in the message
536  ldata = 0
537  do i=1,nrow
538  if(ityp(i)==1 .or. ityp(i)==2) then
539  ! Row i of the compression matrix contains numeric values, so kmis(i) will store .true. if any such values are
540  ! "missing", or .false. otherwise
541  imiss = 2_8**iwid(i)-1
542  if(icol==1) then
543  kmin(i) = imiss
544  kmax(i) = 0
545  kmis(i) = .false.
546  endif
547  do j=icol,ncol
548  if(matx(i,j)<imiss) then
549  kmin(i) = min(kmin(i),matx(i,j))
550  kmax(i) = max(kmax(i),matx(i,j))
551  else
552  kmis(i) = .true.
553  endif
554  enddo
555  kmiss = kmis(i) .and. kmin(i)<imiss
556  range = real(max(1,kmax(i)-kmin(i)+1))
557  if(ityp(i)==2 .and. (range>1. .or. kmiss)) then
558  ! The data values in row i of the compression matrix are numeric values that aren't all identical. Compute the
559  ! number of bits needed to hold the largest of the increments.
560  kbit(i) = nint(log(range)*rln2)
561  if(2**kbit(i)-1<=range) kbit(i) = kbit(i)+1
562  ! However, under no circumstances should this number ever exceed the width of the original underlying descriptor!
563  if(kbit(i)>iwid(i)) kbit(i) = iwid(i)
564  else
565  ! The data values in row i of the compression matrix are numeric values that are all identical, so the increments
566  ! will be omitted from the message.
567  kbit(i) = 0
568  endif
569  ldata = ldata + iwid(i) + 6 + ncol*kbit(i)
570  elseif(ityp(i)==3) then
571  ! Row i of the compression matrix contains character values, so kmis(i) will store .false. if all such values are
572  ! identical, OR .true. otherwise
573  if(icol==1) then
574  cstr(i) = catx(i,1)
575  kmis(i) = .false.
576  endif
577  do j=icol,ncol
578  if ( (.not.kmis(i)) .and. (cstr(i)/=catx(i,j)) ) then
579  kmis(i) = .true.
580  endif
581  enddo
582  if (kmis(i)) then
583  ! The data values in row i of the compression matrix are character values that are not all identical
584  kbit(i) = iwid(i)
585  else
586  ! The data values in row i of the compression matrix are character values that are all identical, so the
587  ! increments will be omitted from the message
588  kbit(i) = 0
589  endif
590  ldata = ldata + iwid(i) + 6 + ncol*kbit(i)
591  endif
592  enddo
593  ! Round data length up to a whole byte count
594  ibyt = (ldata+8-mod(ldata,8))/8
595  ! Depending on the edition number of the message, we need to ensure that we round to an even byte count
596  if( (.not.edge4) .and. (mod(ibyt,2)/=0) ) ibyt = ibyt+1
597  jbit = ibyt*8-ldata
598  if(msgfull(ibyt,kbyt,maxbyt)) then
599  ! The current subset will not fit into the current message. Set the flag to indicate that a message write is needed,
600  ! then go back and re-compress the Section 4 data for this message while excluding the data for the current subset,
601  ! which will be held and stored as the first subset of a new message after writing the current message.
602  writ1 = .true.
603  ncol = ncol-1
604  icol = 1
605  elseif(.not.writ1) then
606  ! Add the current subset to the current message and return
607  call usrtpl(lun,1,1)
608  nsub(lun) = -ncol
609  return
610  else
611  ! Exit the loop and proceed to write out the current message
612  cmpres = .false.
613  endif
614  enddo
615 
616  ! Write the complete compressed message. First, we need to do another call to cmsgini() to initialize Sections 0, 1, 2,
617  ! and 3 of the final compressed BUFR message that will be written out.
618 
619  call cmsgini(lun,mgwa,subset,idate(lun),ncol,ibyt)
620 
621  ! Now add the Section 4 data
622 
623  ibit = ibyt*8
624  do i=1,nrow
625  if(ityp(i)==1.or.ityp(i)==2) then
626  call pkb8(kmin(i),iwid(i),mgwa,ibit)
627  call pkb(kbit(i),6,mgwa,ibit)
628  if(kbit(i)>0) then
629  do j=1,ncol
630  if(matx(i,j)<2_8**iwid(i)-1) then
631  incr = matx(i,j)-kmin(i)
632  else
633  incr = 2_8**kbit(i)-1
634  endif
635  call pkb8(incr,kbit(i),mgwa,ibit)
636  enddo
637  endif
638  elseif(ityp(i)==3) then
639  nchr = iwid(i)/8
640  if(kbit(i)>0) then
641  call ipkm(czero,1,0)
642  do j=1,nchr
643  call pkc(czero,1,mgwa,ibit)
644  enddo
645  call pkb(nchr,6,mgwa,ibit)
646  do j=1,ncol
647  call pkc(catx(i,j),nchr,mgwa,ibit)
648  enddo
649  else
650  call pkc(cstr(i),nchr,mgwa,ibit)
651  call pkb(0,6,mgwa,ibit)
652  endif
653  endif
654  enddo
655 
656  ! Pad the end of Section 4 with zeroes up to the necessary byte count
657 
658  call pkb(0,jbit,mgwa,ibit)
659 
660  ! Add Section 5
661 
662  call pkc(bmcstr,nby5,mgwa,ibit)
663 
664  ! Check that the message byte counters agree, then write the message
665 
666  if(mod(ibit,8)/=0) call bort('BUFRLIB: WRCMPS - THE NUMBER OF BITS IN THE '// &
667  'COMPRESSED BUFR MSG IS NOT A MULTIPLE OF 8 - MSG MUST END ON A BYTE BOUNDARY')
668  lbyt = iupbs01(mgwa,'LENM')
669  nbyt = ibit/8
670  if(nbyt/=lbyt) then
671  write(bort_str,'("BUFRLIB: WRCMPS - OUTPUT MESSAGE LENGTH FROM '// &
672  'SECTION 0",I6," DOES NOT EQUAL FINAL PACKED MESSAGE LENGTH (",I6,")")') lbyt,nbyt
673  call bort(bort_str)
674  endif
675 
676  call msgwrt(lunit,mgwa,nbyt)
677 
678  ! Now, unless this was a "flush" call to this subroutine, go back and initialize a new message to hold the current subset
679  ! that we weren't able to fit into the message that was just written out.
680 
681  first = .true.
682  if(flush) return
683  end do
684 
685 end subroutine wrcmps
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 bort(str)
Log an error message, then either return to or abort the application program.
Definition: borts.F90:15
subroutine bort_target_unset
Clear any existing bort target.
Definition: borts.F90:180
integer function bort_target_set()
Sets a new bort target, if bort catching is enabled and such a target doesn't already exist.
Definition: borts.F90:160
subroutine upb(nval, nbits, ibay, ibit)
Decode an integer value from within a specified number of bits of an integer array,...
Definition: cidecode.F90:202
real *8 function ups(ival, node)
Unpack a real*8 value from an integer by applying the proper scale and reference values.
Definition: cidecode.F90:332
subroutine up8(nval, nbits, ibay, ibit)
Decode an 8-byte integer value from within a specified number of bits of an integer array,...
Definition: cidecode.F90:128
subroutine upc(chr, nchr, ibay, ibit, cnvnull)
Decode a character string from within a specified number of bytes of an integer array,...
Definition: cidecode.F90:26
subroutine pkc(chr, nchr, ibay, ibit)
Encode a character string within a specified number of bytes of an integer array, starting at the bit...
Definition: ciencode.F90:25
recursive subroutine ipkm(cbay, nbyt, n)
Encode an integer value within a specified number of bytes of a character string, up to a maximum of ...
Definition: ciencode.F90:194
subroutine pkb(nval, nbits, ibay, ibit)
Encode an integer value within a specified number of bits of an integer array, starting at the bit im...
Definition: ciencode.F90:140
subroutine pkb8(nval, nbits, ibay, ibit)
Encode an 8-byte integer value within a specified number of bits of an integer array,...
Definition: ciencode.F90:97
subroutine rdcmps(lun)
Read the next compressed BUFR data subset into internal arrays.
Definition: compress.F90:122
subroutine cmsgini(lun, mesg, subset, idate, nsub, nbyt)
Initialize a new BUFR message for output in compressed format.
Definition: compress.F90:271
recursive subroutine cmpmsg(cf)
Specify whether BUFR messages output by future calls to message-writing subroutines and subset-writin...
Definition: compress.F90:33
recursive subroutine writcp(lunit)
Write a data subset into a BUFR message using compression.
Definition: compress.F90:86
subroutine wrcmps(lunix)
Write a compressed BUFR data subset.
Definition: compress.F90:396
subroutine nemtba(lun, nemo, mtyp, msbt, inod)
Get information about a Table A descriptor from the internal DX BUFR tables.
Definition: dxtable.F90:1244
subroutine nemtab(lun, nemo, idn, tab, iret)
Get information about a descriptor, based on a mnemonic.
Definition: fxy.F90:434
subroutine capit(str)
Capitalize all of the alphabetic characters in a string.
Definition: misc.F90:334
Wrap C NCEPLIBS-bufr functions so they can be called from within the Fortran part of the library.
Definition: bufrlib.F90:11
Declare arrays and variables used to store BUFR messages internally for multiple file IDs.
integer, dimension(:), allocatable ibay
Current data subset.
integer ibit
Bit pointer within ibay.
integer, dimension(:,:), allocatable mbay
Current BUFR message for each file ID.
integer, dimension(:), allocatable mbyt
Length (in bytes) of current BUFR message for each file ID.
integer maxbyt
Maximum length of an output BUFR message.
Declare arrays and variables needed for the storage of data values needed when writing compressed dat...
integer ncol
Number of data subsets in message.
integer *8 incr
Increment used when compressing non-character data values.
character *(:), dimension(:,:), allocatable catx
Character data values for all data subsets in message.
integer *8, dimension(:,:), allocatable matx
Non-character data values for all data subsets in message.
Declare arrays and variable needed for the storage of data values needed when writing compressed data...
character *(:), dimension(:), allocatable cstr
Character data value, if corresponding ityp value is set to 3.
integer kbyt
Number of bytes required to store Sections 0, 1, 2, and 3 of message.
logical flush
Flush flag.
integer nrow
Number of data values for each data subset in message.
integer *8 imiss
"Missing" value used when compressing non-character data values.
integer *8, dimension(:), allocatable kmax
Maximum of each data value across all data subsets in message.
integer, dimension(:), allocatable jlnode
Jump/link table node corresponding to each data value.
logical writ1
Write-out flag.
integer, dimension(:), allocatable ityp
Type of each data value:
integer, dimension(:), allocatable iwid
Bit width of underlying data descriptor as defined within Table B for each data value.
integer lunc
File ID for output file.
integer, dimension(:), allocatable kbit
Number of bits needed to hold the increments for this data value within each data subset of the messa...
logical, dimension(:), allocatable kmis
"Missing" values flag.
integer *8, dimension(:), allocatable kmin
Minimum of each data value across all data subsets in message.
Declare an array used by various subroutines and functions to hold a temporary working copy of a BUFR...
integer, dimension(:), allocatable mgwa
Temporary working copy of BUFR message.
Declare a variable used to indicate whether output BUFR messages should be compressed.
character ccmf
Flag indicating whether BUFR output messages are to be compressed; this variable is initialized to a ...
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.
integer, dimension(:), allocatable idate
Section 1 date-time of message.
integer, dimension(:), allocatable msub
Total number of data subsets in message.
integer, dimension(:), allocatable nsub
Current subset pointer within message.
Declare arrays and variables needed to store information about long character strings (greater than 8...
integer nrst
Number of long character strings in data subset.
integer, dimension(:), allocatable irnch
Lengths (in bytes) of long character strings.
integer, dimension(:), allocatable irbit
Pointers in data subset to first bits of long character strings.
character *10, dimension(:), allocatable crtag
Table B mnemonics associated with long character strings.
Declare arrays and variables used to store custom values for certain mnemonics within Sections 0 and ...
integer, dimension(:), allocatable ivmnem
Custom values for use within Sections 0 and 1 of all future output BUFR messages written to all Fortr...
integer ns01v
Number of custom values stored.
character *8, dimension(:), allocatable cmnem
Section 0 and 1 mnemonics corresponding to ivmnem.
Declare an array used to store a status code for each file ID if an error or other abnormal result oc...
integer, dimension(:), allocatable iscodes
Abnormal status codes.
Declare arrays and variables used to store the internal jump/link table.
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.
real *8, dimension(:,:), allocatable, target val
Data values.
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 msgwrt(lunit, mesg, mgbyt)
Perform final checks and updates on a BUFR message before writing it to a specified Fortran logical u...
subroutine usrtpl(lun, invn, nbmp)
Expand a subset template within internal arrays.
recursive subroutine writsb(lunit)
Write a complete data subset into a BUFR message, for eventual output to logical unit lunit.
subroutine x84(iin8, iout4, nval)
Encode one or more 8-byte integer values as 4-byte integer values.
Definition: x4884.F90:65