NCEPLIBS-g2  3.5.0
compack.F90
Go to the documentation of this file.
1 
9 
42 subroutine cmplxpack(fld,ndpts,idrsnum,idrstmpl,cpack,lcpack)
43 
44  integer,intent(in) :: ndpts,idrsnum
45  real,intent(in) :: fld(ndpts)
46  character(len=1),intent(out) :: cpack(*)
47  integer,intent(inout) :: idrstmpl(*)
48  integer,intent(out) :: lcpack
49 
50  if ( idrstmpl(7) .eq. 0 ) then ! No internal missing values
51  call compack(fld,ndpts,idrsnum,idrstmpl,cpack,lcpack)
52  elseif ( idrstmpl(7).eq.1 .OR. idrstmpl(7).eq.2) then
53  call misspack(fld,ndpts,idrsnum,idrstmpl,cpack,lcpack)
54  else
55  print *,'cmplxpack: Do not recognize Missing value option.'
56  lcpack=-1
57  endif
58 
59  return
60 end subroutine cmplxpack
61 
88 subroutine compack(fld,ndpts,idrsnum,idrstmpl,cpack,lcpack)
89 
90  use intmath
91  implicit none
92  integer,intent(in) :: ndpts,idrsnum
93  real,intent(in) :: fld(ndpts)
94  character(len=1),intent(out) :: cpack(*)
95  integer,intent(inout) :: idrstmpl(*)
96  integer,intent(out) :: lcpack
97 
98  real :: bscale,dscale
99  integer :: j,iofst,imin,ival1,ival2,minsd,nbitsd,n
100  integer :: igmax,nbitsgref,left,iwmax,i,ilmax,kk,ij
101  integer :: ngwidthref,nbitsgwidth,nglenref,nglenlast
102  integer :: maxorig,nbitorig,isd,ngroups,itemp,minpk
103  integer :: inc,maxgrps,missopt,miss1,miss2,lg
104  integer :: ibit,jbit,kbit,novref,lbitref,ier,ng,imax
105  integer :: nbitsglen
106  real(4) :: ref,rmin4
107  real(8) :: rmin,rmax
108 
109  integer(4) :: iref
110  integer,allocatable :: ifld(:)
111  integer,allocatable :: jmin(:),jmax(:),lbit(:)
112  integer,parameter :: zero=0
113  integer,allocatable :: gref(:),gwidth(:),glen(:)
114  integer :: glength,grpwidth
115  logical :: simple_alg
116 
117  simple_alg = .false.
118 
119  bscale=2.0**real(-idrstmpl(2))
120  dscale=10.0**real(idrstmpl(3))
121  !
122  ! Find max and min values in the data
123  !
124  if(ndpts>0) then
125  rmax=fld(1)
126  rmin=fld(1)
127  else
128  rmax=1.0
129  rmin=1.0
130  endif
131  do j=2,ndpts
132  if (fld(j).gt.rmax) rmax=fld(j)
133  if (fld(j).lt.rmin) rmin=fld(j)
134  enddo
135  !
136  ! If max and min values are not equal, pack up field.
137  ! If they are equal, we have a constant field, and the reference
138  ! value (rmin) is the value for each point in the field and
139  ! set nbits to 0.
140  !
141  multival: if (rmin.ne.rmax) then
142  iofst=0
143  allocate(ifld(ndpts))
144  allocate(gref(ndpts))
145  allocate(gwidth(ndpts))
146  allocate(glen(ndpts))
147  !
148  ! Scale original data
149  !
150  if (idrstmpl(2).eq.0) then ! No binary scaling
151  imin=nint(rmin*dscale)
152  !imax=nint(rmax*dscale)
153  rmin=real(imin)
154  do j=1,ndpts
155  ifld(j)=max(0,nint(fld(j)*dscale)-imin)
156  enddo
157  else ! Use binary scaling factor
158  rmin=rmin*dscale
159  !rmax=rmax*dscale
160  do j=1,ndpts
161  ifld(j)=max(0,nint(((fld(j)*dscale)-rmin)*bscale))
162  enddo
163  endif
164  !
165  ! Calculate Spatial differences, if using DRS Template 5.3
166  !
167  alg3: if (idrsnum.eq.3) then ! spatial differences
168  if (idrstmpl(17).ne.1.and.idrstmpl(17).ne.2) idrstmpl(17)=2
169  if (idrstmpl(17).eq.1) then ! first order
170  ival1=ifld(1)
171  if(ival1<0) then
172  print *,'G2: negative ival1',ival1
173  stop 101
174  endif
175  do j=ndpts,2,-1
176  ifld(j)=ifld(j)-ifld(j-1)
177  enddo
178  ifld(1)=0
179  elseif (idrstmpl(17).eq.2) then ! second order
180  ival1=ifld(1)
181  ival2=ifld(2)
182  if(ival1<0) then
183  print *,'G2: negative ival1',ival1
184  stop 11
185  endif
186  if(ival2<0) then
187  print *,'G2: negative ival2',ival2
188  stop 12
189  endif
190  do j=ndpts,3,-1
191  ifld(j)=ifld(j)-(2*ifld(j-1))+ifld(j-2)
192  enddo
193  ifld(1)=0
194  ifld(2)=0
195  endif
196  !
197  ! subtract min value from spatial diff field
198  !
199  isd=idrstmpl(17)+1
200  minsd=minval(ifld(isd:ndpts))
201  do j=isd,ndpts
202  ifld(j)=ifld(j)-minsd
203  enddo
204  !
205  ! find num of bits need to store minsd and add 1 extra bit
206  ! to indicate sign
207  !
208  nbitsd=i1log2(abs(minsd))+1
209  !
210  ! find num of bits need to store ifld(1) ( and ifld(2)
211  ! if using 2nd order differencing )
212  !
213  maxorig=ival1
214  if (idrstmpl(17).eq.2.and.ival2.gt.ival1) maxorig=ival2
215  nbitorig=i1log2(maxorig)+1
216  if (nbitorig.gt.nbitsd) nbitsd=nbitorig
217  ! increase number of bits to even multiple of 8 ( octet )
218  if (mod(nbitsd,8).ne.0) nbitsd=nbitsd+(8-mod(nbitsd,8))
219  !
220  ! Store extra spatial differencing info into the packed
221  ! data section.
222  !
223  if (nbitsd.ne.0) then
224  ! pack first original value
225  if (ival1.ge.0) then
226  call g2_sbytec(cpack,ival1,iofst,nbitsd)
227  iofst=iofst+nbitsd
228  else
229  call g2_sbytec(cpack,1,iofst,1)
230  iofst=iofst+1
231  call g2_sbytec(cpack,iabs(ival1),iofst,nbitsd-1)
232  iofst=iofst+nbitsd-1
233  endif
234  if (idrstmpl(17).eq.2) then
235  ! pack second original value
236  if (ival2.ge.0) then
237  call g2_sbytec(cpack,ival2,iofst,nbitsd)
238  iofst=iofst+nbitsd
239  else
240  call g2_sbytec(cpack,1,iofst,1)
241  iofst=iofst+1
242  call g2_sbytec(cpack,iabs(ival2),iofst,nbitsd-1)
243  iofst=iofst+nbitsd-1
244  endif
245  endif
246  ! pack overall min of spatial differences
247  if (minsd.ge.0) then
248  call g2_sbytec(cpack,minsd,iofst,nbitsd)
249  iofst=iofst+nbitsd
250  else
251  call g2_sbytec(cpack,1,iofst,1)
252  iofst=iofst+1
253  call g2_sbytec(cpack,iabs(minsd),iofst,nbitsd-1)
254  iofst=iofst+nbitsd-1
255  endif
256  endif
257  !print *,'SDp ',ival1,ival2,minsd,nbitsd
258  endif alg3 ! end of spatial diff section
259  !
260  ! Determine Groups to be used.
261  !
262  simplealg: if ( simple_alg ) then
263  ! set group length to 10 : calculate number of groups
264  ! and length of last group
265  print *,'G2: use simple algorithm'
266  ngroups=ndpts/10
267  glen(1:ngroups)=10
268  itemp=mod(ndpts,10)
269  if (itemp.ne.0) then
270  ngroups=ngroups+1
271  glen(ngroups)=itemp
272  endif
273  else
274  ! Use Dr. Glahn's algorithm for determining grouping.
275  !
276  minpk=10
277  inc=1
278  maxgrps=((ndpts+minpk-1)/minpk)
279  allocate(jmin(maxgrps))
280  allocate(jmax(maxgrps))
281  allocate(lbit(maxgrps))
282  missopt=0
283  call pack_gp(ifld,ndpts,missopt,minpk,inc,miss1,miss2, &
284  jmin,jmax,lbit,glen,maxgrps,ngroups,ibit,jbit, &
285  kbit,novref,lbitref,ier)
286  if(ier/=0) then
287  ! Dr. Glahn's algorithm failed; use simple packing method instead.
288 1099 format('G2: fall back to simple algorithm (glahn ier=',i0,')')
289  print 1099,ier
290  ngroups=ndpts/10
291  glen(1:ngroups)=10
292  itemp=mod(ndpts,10)
293  if (itemp.ne.0) then
294  ngroups=ngroups+1
295  glen(ngroups)=itemp
296  endif
297  elseif(ngroups<1) then
298  ! Dr. Glahn's algorithm failed; use simple packing method instead.
299  print *,'Glahn algorithm failed; use simple packing'
300  ngroups=ndpts/10
301  glen(1:ngroups)=10
302  itemp=mod(ndpts,10)
303  if (itemp.ne.0) then
304  ngroups=ngroups+1
305  glen(ngroups)=itemp
306  endif
307  else
308  !print *,'SAGier = ',ier,ibit,jbit,kbit,novref,lbitref
309  do ng=1,ngroups
310  glen(ng)=glen(ng)+novref
311  enddo
312  deallocate(jmin)
313  deallocate(jmax)
314  deallocate(lbit)
315  endif
316  endif simplealg
317  !
318  ! For each group, find the group's reference value
319  ! and the number of bits needed to hold the remaining values
320  !
321  n=1
322  do ng=1,ngroups
323  ! find max and min values of group
324  gref(ng)=ifld(n)
325  imax=ifld(n)
326  j=n+1
327  do lg=2,glen(ng)
328  if (ifld(j).lt.gref(ng)) gref(ng)=ifld(j)
329  if (ifld(j).gt.imax) imax=ifld(j)
330  j=j+1
331  enddo
332  ! calc num of bits needed to hold data
333  if ( gref(ng).ne.imax ) then
334  gwidth(ng)=i1log2(imax-gref(ng))
335  else
336  gwidth(ng)=0
337  endif
338  ! Subtract min from data
339  j=n
340  do lg=1,glen(ng)
341  ifld(j)=ifld(j)-gref(ng)
342  j=j+1
343  enddo
344  ! increment fld array counter
345  n=n+glen(ng)
346  enddo
347  !
348  ! Find max of the group references and calc num of bits needed
349  ! to pack each groups reference value, then
350  ! pack up group reference values
351  !
352  !write(77,*)'GREFS: ',(gref(j),j=1,ngroups)
353  igmax=maxval(gref(1:ngroups))
354  if (igmax.ne.0) then
355  nbitsgref=i1log2(igmax)
356  call g2_sbytesc(cpack,gref,iofst,nbitsgref,0,ngroups)
357  itemp=nbitsgref*ngroups
358  iofst=iofst+itemp
359  if (mod(itemp,8).ne.0) then
360  left=8-mod(itemp,8)
361  call g2_sbytec(cpack,zero,iofst,left)
362  iofst=iofst+left
363  endif
364  else
365  nbitsgref=0
366  endif
367  !
368  ! Find max/min of the group widths and calc num of bits needed
369  ! to pack each groups width value, then
370  ! pack up group width values
371  !
372  !write(77,*)'GWIDTHS: ',(gwidth(j),j=1,ngroups)
373  iwmax=maxval(gwidth(1:ngroups))
374  ngwidthref=minval(gwidth(1:ngroups))
375  if (iwmax.ne.ngwidthref) then
376  nbitsgwidth=i1log2(iwmax-ngwidthref)
377  do i=1,ngroups
378  gwidth(i)=gwidth(i)-ngwidthref
379  if(gwidth(i)<0) then
380  write(0,*) 'i,gw,ngw=',i,gwidth(i),ngwidthref
381  stop 9
382  endif
383  enddo
384  call g2_sbytesc(cpack,gwidth,iofst,nbitsgwidth,0,ngroups)
385  itemp=nbitsgwidth*ngroups
386  iofst=iofst+itemp
387  ! Pad last octet with Zeros, if necessary,
388  if (mod(itemp,8).ne.0) then
389  left=8-mod(itemp,8)
390  call g2_sbytec(cpack,zero,iofst,left)
391  iofst=iofst+left
392  endif
393  else
394  nbitsgwidth=0
395  gwidth(1:ngroups)=0
396  endif
397  !
398  ! Find max/min of the group lengths and calc num of bits needed
399  ! to pack each groups length value, then
400  ! pack up group length values
401  !
402  !write(77,*)'GLENS: ',(glen(j),j=1,ngroups)
403  ilmax=maxval(glen(1:ngroups-1))
404  nglenref=minval(glen(1:ngroups-1))
405  nglenlast=glen(ngroups)
406  if (ilmax.ne.nglenref) then
407  nbitsglen=i1log2(ilmax-nglenref)
408  do i=1,ngroups-1
409  glen(i)=glen(i)-nglenref
410  if(glen(i)<0) then
411  write(0,*) 'i,glen(i) = ',i,glen(i)
412  stop 23
413  endif
414  enddo
415  call g2_sbytesc(cpack,glen,iofst,nbitsglen,0,ngroups)
416  itemp=nbitsglen*ngroups
417  iofst=iofst+itemp
418  ! Pad last octet with Zeros, if necessary,
419  if (mod(itemp,8).ne.0) then
420  left=8-mod(itemp,8)
421  call g2_sbytec(cpack,zero,iofst,left)
422  iofst=iofst+left
423  endif
424  else
425  nbitsglen=0
426  glen(1:ngroups)=0
427  endif
428  !
429  ! For each group, pack data values
430  !
431  !write(77,*)'IFLDS: ',(ifld(j),j=1,ndpts)
432  n=1
433  ij=0
434  do ng=1,ngroups
435  glength=glen(ng)+nglenref
436  if (ng.eq.ngroups ) glength=nglenlast
437  grpwidth=gwidth(ng)+ngwidthref
438  !write(77,*)'NGP ',ng,grpwidth,glength,gref(ng)
439  if ( grpwidth.ne.0 ) then
440  call g2_sbytesc(cpack,ifld(n),iofst,grpwidth,0,glength)
441  iofst=iofst+(grpwidth*glength)
442  endif
443  do kk=1,glength
444  ij=ij+1
445  !write(77,*)'SAG ',ij,fld(ij),ifld(ij),gref(ng),bscale,rmin,dscale
446  enddo
447  n=n+glength
448  enddo
449  ! Pad last octet with Zeros, if necessary,
450  if (mod(iofst,8).ne.0) then
451  left=8-mod(iofst,8)
452  call g2_sbytec(cpack,zero,iofst,left)
453  iofst=iofst+left
454  endif
455  lcpack=iofst/8
456  !
457  if ( allocated(ifld) ) deallocate(ifld)
458  if ( allocated(gref) ) deallocate(gref)
459  if ( allocated(gwidth) ) deallocate(gwidth)
460  if ( allocated(glen) ) deallocate(glen)
461  else ! Constant field ( max = min )
462  lcpack=0
463  nbitsgref=0
464  ngroups=0
465  ngwidthref=0
466  nbitsgwidth=0
467  nglenref=0
468  nglenlast=0
469  nbitsglen=0
470  nbitsd=0
471  endif multival
472 
473  !
474  ! Fill in ref value and number of bits in Template 5.2
475  !
476  rmin4 = real(rmin, 4)
477  call mkieee(rmin4,ref,1) ! ensure reference value is IEEE format
478  ! call g2_gbytec(ref,idrstmpl(1),0,32)
479  iref=transfer(ref,iref)
480  idrstmpl(1)=iref
481  idrstmpl(4)=nbitsgref
482  idrstmpl(5)=0 ! original data were reals
483  idrstmpl(6)=1 ! general group splitting
484  idrstmpl(7)=0 ! No internal missing values
485  idrstmpl(8)=0 ! Primary missing value
486  idrstmpl(9)=0 ! secondary missing value
487  idrstmpl(10)=ngroups ! Number of groups
488  idrstmpl(11)=ngwidthref ! reference for group widths
489  idrstmpl(12)=nbitsgwidth ! num bits used for group widths
490  idrstmpl(13)=nglenref ! Reference for group lengths
491  idrstmpl(14)=1 ! length increment for group lengths
492  idrstmpl(15)=nglenlast ! True length of last group
493  idrstmpl(16)=nbitsglen ! num bits used for group lengths
494  if (idrsnum.eq.3) then
495  idrstmpl(18)=nbitsd/8 ! num bits used for extra spatial
496  ! differencing values
497  endif
498 
499 end subroutine compack
500 
526 subroutine comunpack(cpack,len,lensec,idrsnum,idrstmpl,ndpts, &
527  fld,ier)
528 
529  character(len=1),intent(in) :: cpack(len)
530  integer,intent(in) :: ndpts,len
531  integer,intent(in) :: idrstmpl(*)
532  real,intent(out) :: fld(ndpts)
533 
534  integer,allocatable :: ifld(:),ifldmiss(:)
535  integer(4) :: ieee
536  integer,allocatable :: gref(:),gwidth(:),glen(:)
537  real :: ref,bscale,dscale,rmiss1,rmiss2
538  ! real :: fldo(6045)
539  integer :: totBit, totLen
540 
541  ier=0
542  !print *,'IDRSTMPL: ',(idrstmpl(j),j=1,16)
543  ieee = idrstmpl(1)
544  call rdieee(ieee,ref,1)
545  bscale = 2.0**real(idrstmpl(2))
546  dscale = 10.0**real(-idrstmpl(3))
547  nbitsgref = idrstmpl(4)
548  itype = idrstmpl(5)
549  ngroups = idrstmpl(10)
550  nbitsgwidth = idrstmpl(12)
551  nbitsglen = idrstmpl(16)
552  if (idrsnum.eq.3) then
553  nbitsd=idrstmpl(18)*8
554  endif
555 
556  ! Constant field
557 
558  if (ngroups.eq.0) then
559  do j=1,ndpts
560  fld(j)=ref
561  enddo
562  return
563  endif
564 
565  iofst=0
566  allocate(ifld(ndpts),stat=is)
567  !print *,'ALLOC ifld: ',is,ndpts
568  allocate(gref(ngroups),stat=is)
569  !print *,'ALLOC gref: ',is
570  allocate(gwidth(ngroups),stat=is)
571  !print *,'ALLOC gwidth: ',is
572  !
573  ! Get missing values, if supplied
574  !
575  if ( idrstmpl(7).eq.1 ) then
576  if (itype.eq.0) then
577  call rdieee(idrstmpl(8),rmiss1,1)
578  else
579  rmiss1=real(idrstmpl(8))
580  endif
581  elseif ( idrstmpl(7).eq.2 ) then
582  if (itype.eq.0) then
583  call rdieee(idrstmpl(8),rmiss1,1)
584  call rdieee(idrstmpl(9),rmiss2,1)
585  else
586  rmiss1=real(idrstmpl(8))
587  rmiss2=real(idrstmpl(9))
588  endif
589  endif
590  !print *,'RMISSs: ',rmiss1,rmiss2,ref
591  !
592  ! Extract Spatial differencing values, if using DRS Template 5.3
593  !
594  if (idrsnum.eq.3) then
595  if (nbitsd.ne.0) then
596  call g2_gbytec(cpack,ival1,iofst,nbitsd)
597  iofst=iofst+nbitsd
598  if (idrstmpl(17).eq.2) then
599  call g2_gbytec(cpack,ival2,iofst,nbitsd)
600  iofst=iofst+nbitsd
601  endif
602  call g2_gbytec(cpack,isign,iofst,1)
603  iofst=iofst+1
604  call g2_gbytec(cpack,minsd,iofst,nbitsd-1)
605  iofst=iofst+nbitsd-1
606  if (isign.eq.1) minsd=-minsd
607  else
608  ival1=0
609  ival2=0
610  minsd=0
611  endif
612  !print *,'SDu ',ival1,ival2,minsd,nbitsd
613  endif
614  !
615  ! Extract Each Group's reference value
616  !
617  !print *,'SAG1: ',nbitsgref,ngroups,iofst
618  if (nbitsgref.ne.0) then
619  call g2_gbytesc(cpack,gref,iofst,nbitsgref,0,ngroups)
620  itemp=nbitsgref*ngroups
621  iofst=iofst+(itemp)
622  if (mod(itemp,8).ne.0) iofst=iofst+(8-mod(itemp,8))
623  else
624  gref(1:ngroups)=0
625  endif
626  !write(78,*)'GREFs: ',(gref(j),j=1,ngroups)
627  !
628  ! Extract Each Group's bit width
629  !
630  !print *,'SAG2: ',nbitsgwidth,ngroups,iofst,idrstmpl(11)
631  if (nbitsgwidth.ne.0) then
632  call g2_gbytesc(cpack,gwidth,iofst,nbitsgwidth,0,ngroups)
633  itemp=nbitsgwidth*ngroups
634  iofst=iofst+(itemp)
635  if (mod(itemp,8).ne.0) iofst=iofst+(8-mod(itemp,8))
636  else
637  gwidth(1:ngroups)=0
638  endif
639  do j=1,ngroups
640  gwidth(j)=gwidth(j)+idrstmpl(11)
641  enddo
642  !write(78,*)'GWIDTHs: ',(gwidth(j),j=1,ngroups)
643  !
644  ! Extract Each Group's length (number of values in each group)
645  !
646  allocate(glen(ngroups),stat=is)
647  !print *,'ALLOC glen: ',is
648  !print *,'SAG3: ',nbitsglen,ngroups,iofst,idrstmpl(14),idrstmpl(13)
649  if (nbitsglen.ne.0) then
650  call g2_gbytesc(cpack,glen,iofst,nbitsglen,0,ngroups)
651  itemp=nbitsglen*ngroups
652  iofst=iofst+(itemp)
653  if (mod(itemp,8).ne.0) iofst=iofst+(8-mod(itemp,8))
654  else
655  glen(1:ngroups)=0
656  endif
657  do j=1,ngroups
658  glen(j)=(glen(j)*idrstmpl(14))+idrstmpl(13)
659  enddo
660  glen(ngroups)=idrstmpl(15)
661  !write(78,*)'GLENs: ',(glen(j),j=1,ngroups)
662  !print *,'GLENsum: ',sum(glen)
663  !
664  ! Test to see if the group widths and lengths are consistent with number of
665  ! values, and length of section 7.
666  !
667  totbit = 0
668  totlen = 0
669  do j=1,ngroups
670  totbit = totbit + (gwidth(j)*glen(j));
671  totlen = totlen + glen(j);
672  enddo
673  if (totlen .NE. ndpts) then
674  ier=1
675  return
676  endif
677  if ( (totbit/8) .GT. lensec) then
678  ier=1
679  return
680  endif
681  !
682  ! For each group, unpack data values
683  !
684  if ( idrstmpl(7).eq.0 ) then ! no missing values
685  n=1
686  do j=1,ngroups
687  !write(78,*)'NGP ',j,gwidth(j),glen(j),gref(j)
688  if (gwidth(j).ne.0) then
689  call g2_gbytesc(cpack,ifld(n),iofst,gwidth(j),0,glen(j))
690  do k=1,glen(j)
691  ifld(n)=ifld(n)+gref(j)
692  n=n+1
693  enddo
694  else
695  ifld(n:n+glen(j)-1)=gref(j)
696  n=n+glen(j)
697  endif
698  iofst=iofst+(gwidth(j)*glen(j))
699  enddo
700  elseif ( idrstmpl(7).eq.1.OR.idrstmpl(7).eq.2 ) then
701  ! missing values included
702  allocate(ifldmiss(ndpts))
703  !ifldmiss=0
704  n=1
705  non=1
706  do j=1,ngroups
707  !print *,'SAGNGP ',j,gwidth(j),glen(j),gref(j)
708  if (gwidth(j).ne.0) then
709  msng1=(2**gwidth(j))-1
710  msng2=msng1-1
711  call g2_gbytesc(cpack,ifld(n),iofst,gwidth(j),0,glen(j))
712  iofst=iofst+(gwidth(j)*glen(j))
713  do k=1,glen(j)
714  if (ifld(n).eq.msng1) then
715  ifldmiss(n)=1
716  elseif (idrstmpl(7).eq.2.AND.ifld(n).eq.msng2) then
717  ifldmiss(n)=2
718  else
719  ifldmiss(n)=0
720  ifld(non)=ifld(n)+gref(j)
721  non=non+1
722  endif
723  n=n+1
724  enddo
725  else
726  msng1=(2**nbitsgref)-1
727  msng2=msng1-1
728  if (gref(j).eq.msng1) then
729  ifldmiss(n:n+glen(j)-1)=1
730  !ifld(n:n+glen(j)-1)=0
731  elseif (idrstmpl(7).eq.2.AND.gref(j).eq.msng2) then
732  ifldmiss(n:n+glen(j)-1)=2
733  !ifld(n:n+glen(j)-1)=0
734  else
735  ifldmiss(n:n+glen(j)-1)=0
736  ifld(non:non+glen(j)-1)=gref(j)
737  non=non+glen(j)
738  endif
739  n=n+glen(j)
740  endif
741  enddo
742  endif
743  !write(78,*)'IFLDs: ',(ifld(j),j=1,ndpts)
744 
745  if ( allocated(gref) ) deallocate(gref)
746  if ( allocated(gwidth) ) deallocate(gwidth)
747  if ( allocated(glen) ) deallocate(glen)
748  !
749  ! If using spatial differences, add overall min value, and
750  ! sum up recursively
751  !
752  if (idrsnum.eq.3) then ! spatial differencing
753  if (idrstmpl(17).eq.1) then ! first order
754  ifld(1)=ival1
755  if ( idrstmpl(7).eq.0 ) then ! no missing values
756  itemp=ndpts
757  else
758  itemp=non-1
759  endif
760  do n=2,itemp
761  ifld(n)=ifld(n)+minsd
762  ifld(n)=ifld(n)+ifld(n-1)
763  enddo
764  elseif (idrstmpl(17).eq.2) then ! second order
765  ifld(1)=ival1
766  ifld(2)=ival2
767  if ( idrstmpl(7).eq.0 ) then ! no missing values
768  itemp=ndpts
769  else
770  itemp=non-1
771  endif
772  do n=3,itemp
773  ifld(n)=ifld(n)+minsd
774  ifld(n)=ifld(n)+(2*ifld(n-1))-ifld(n-2)
775  enddo
776  endif
777  !write(78,*)'IFLDs: ',(ifld(j),j=1,ndpts)
778  endif
779  !
780  ! Scale data back to original form
781  !
782  !print *,'SAGT: ',ref,bscale,dscale
783  if ( idrstmpl(7).eq.0 ) then ! no missing values
784  do n=1,ndpts
785  fld(n)=((real(ifld(n))*bscale)+ref)*dscale
786  !write(78,*)'SAG ',n,fld(n),ifld(n),bscale,ref,1./dscale
787  enddo
788  elseif ( idrstmpl(7).eq.1.OR.idrstmpl(7).eq.2 ) then
789  ! missing values included
790  non=1
791  do n=1,ndpts
792  if ( ifldmiss(n).eq.0 ) then
793  fld(n)=((real(ifld(non))*bscale)+ref)*dscale
794  !print *,'SAG ',n,fld(n),ifld(non),bscale,ref,dscale
795  non=non+1
796  elseif ( ifldmiss(n).eq.1 ) then
797  fld(n)=rmiss1
798  elseif ( ifldmiss(n).eq.2 ) then
799  fld(n)=rmiss2
800  endif
801  enddo
802  if ( allocated(ifldmiss) ) deallocate(ifldmiss)
803  endif
804 
805  if ( allocated(ifld) ) deallocate(ifld)
806 
807  !open(10,form='unformatted',recl=24180,access='direct')
808  !read(10,rec=1) (fldo(k),k=1,6045)
809  !do i =1,6045
810  ! print *,i,fldo(i),fld(i),fldo(i)-fld(i)
811  !enddo
812 
813  return
814 end subroutine comunpack
815 
854 subroutine misspack(fld,ndpts,idrsnum,idrstmpl,cpack,lcpack)
855 
856  use intmath
857  integer,intent(in) :: ndpts,idrsnum
858  real,intent(in) :: fld(ndpts)
859  character(len=1),intent(out) :: cpack(*)
860  integer,intent(inout) :: idrstmpl(*)
861  integer,intent(out) :: lcpack
862 
863  real(4) :: ref, rmin4
864  integer(4) :: iref
865  integer,allocatable :: ifld(:),ifldmiss(:),jfld(:)
866  integer,allocatable :: jmin(:),jmax(:),lbit(:)
867  integer,parameter :: zero=0
868  integer,allocatable :: gref(:),gwidth(:),glen(:)
869  integer :: glength,grpwidth
870  logical :: simple_alg
871  logical :: have_rmin
872 
873  simple_alg = .false.
874  have_rmin = .false.
875  bscale=2.0**real(-idrstmpl(2))
876  dscale=10.0**real(idrstmpl(3))
877  missopt=idrstmpl(7)
878  if ( missopt.ne.1 .AND. missopt.ne.2 ) then
879  print *,'misspack: Unrecognized option.'
880  lcpack=-1
881  return
882  else ! Get missing values
883  call rdieee(idrstmpl(8),rmissp,1)
884  if (missopt.eq.2) call rdieee(idrstmpl(9),rmisss,1)
885  endif
886 
887  ! Find min value of non-missing values in the data,
888  ! AND set up missing value mapping of the field.
889  allocate(ifldmiss(ndpts))
890 
891  if ( missopt .eq. 1 ) then ! Primary missing value only
892  do j=1,ndpts
893  if (fld(j).eq.rmissp) then
894  ifldmiss(j)=1
895  else
896  ifldmiss(j)=0
897  if(have_rmin) then
898  if (fld(j).lt.rmin) rmin=fld(j)
899  else
900  rmin=fld(j)
901  have_rmin=.true.
902  endif
903  endif
904  enddo
905  if(.not.have_rmin) rmin=rmissp
906  endif
907  if ( missopt .eq. 2 ) then ! Primary and secondary missing values
908  do j=1,ndpts
909  if (fld(j).eq.rmissp) then
910  ifldmiss(j)=1
911  elseif (fld(j).eq.rmisss) then
912  ifldmiss(j)=2
913  else
914  ifldmiss(j)=0
915  if(have_rmin) then
916  if (fld(j).lt.rmin) rmin=fld(j)
917  else
918  rmin=fld(j)
919  have_rmin=.true.
920  endif
921  endif
922  if(.not.have_rmin) rmin=rmissp
923  enddo
924  endif
925 
926  ! Allocate work arrays:
927  ! Note: -ifldmiss(j),j=1,ndpts is a map of original field indicating
928  ! which of the original data values
929  ! are primary missing (1), sencondary missing (2) or non-missing (0).
930  ! -jfld(j),j=1,nonmiss is a subarray of just the non-missing values from
931  ! the original field.
932  iofst=0
933  allocate(ifld(ndpts))
934  allocate(jfld(ndpts))
935  allocate(gref(ndpts))
936  allocate(gwidth(ndpts))
937  allocate(glen(ndpts))
938  !
939  ! Scale original data
940  !
941  nonmiss=0
942  if (idrstmpl(2).eq.0) then ! No binary scaling
943  imin=nint(rmin*dscale)
944  !imax=nint(rmax*dscale)
945  rmin=real(imin)
946  do j=1,ndpts
947  if (ifldmiss(j).eq.0) then
948  nonmiss=nonmiss+1
949  jfld(nonmiss)=max(0,nint(fld(j)*dscale)-imin)
950  endif
951  enddo
952  else ! Use binary scaling factor
953  rmin=rmin*dscale
954  do j=1,ndpts
955  if (ifldmiss(j).eq.0) then
956  nonmiss=nonmiss+1
957  jfld(nonmiss)=max(0,nint(((fld(j)*dscale)-rmin)*bscale))
958  endif
959  enddo
960  endif
961  !
962  ! Calculate Spatial differences, if using DRS Template 5.3
963  !
964  if (idrsnum.eq.3) then ! spatial differences
965  if (idrstmpl(17).ne.1.and.idrstmpl(17).ne.2) idrstmpl(17)=2
966  if (idrstmpl(17).eq.1) then ! first order
967  if(nonmiss<1) then
968  ival1=1.0
969  else
970  ival1=jfld(1)
971  endif
972  do j=nonmiss,2,-1
973  jfld(j)=jfld(j)-jfld(j-1)
974  enddo
975  if(nonmiss>0) jfld(1)=0
976  elseif (idrstmpl(17).eq.2) then ! second order
977  if(nonmiss==1) then
978  ival1=jfld(1)
979  ival2=jfld(1)
980  elseif(nonmiss<1) then
981  ival1=1.0
982  ival2=1.0
983  else
984  ival1=jfld(1)
985  ival2=jfld(2)
986  endif
987  do j=nonmiss,3,-1
988  jfld(j)=jfld(j)-(2*jfld(j-1))+jfld(j-2)
989  enddo
990  if(nonmiss>=1) jfld(1)=0
991  if(nonmiss>=2) jfld(2)=0
992  endif
993 
994  ! subtract min value from spatial diff field
995  isd=idrstmpl(17)+1
996  minsd=minval(jfld(isd:nonmiss))
997  do j=isd,nonmiss
998  jfld(j)=jfld(j)-minsd
999  enddo
1000 
1001  ! find num of bits need to store minsd and add 1 extra bit
1002  ! to indicate sign
1003  temp=i1log2(abs(minsd))
1004  nbitsd=ceiling(temp)+1
1005 
1006  ! find num of bits need to store ifld(1) ( and ifld(2)
1007  ! if using 2nd order differencing )
1008  maxorig=ival1
1009  if (idrstmpl(17).eq.2.and.ival2.gt.ival1) maxorig=ival2
1010  temp=i1log2(maxorig)
1011  nbitorig=ceiling(temp)+1
1012  if (nbitorig.gt.nbitsd) nbitsd=nbitorig
1013  ! increase number of bits to even multiple of 8 ( octet )
1014  if (mod(nbitsd,8).ne.0) nbitsd=nbitsd+(8-mod(nbitsd,8))
1015 
1016  ! Store extra spatial differencing info into the packed
1017  ! data section.
1018  if (nbitsd.ne.0) then
1019  ! pack first original value
1020  if (ival1.ge.0) then
1021  call g2_sbytec(cpack,ival1,iofst,nbitsd)
1022  iofst=iofst+nbitsd
1023  else
1024  call g2_sbytec(cpack,1,iofst,1)
1025  iofst=iofst+1
1026  call g2_sbytec(cpack,iabs(ival1),iofst,nbitsd-1)
1027  iofst=iofst+nbitsd-1
1028  endif
1029  if (idrstmpl(17).eq.2) then
1030  ! pack second original value
1031  if (ival2.ge.0) then
1032  call g2_sbytec(cpack,ival2,iofst,nbitsd)
1033  iofst=iofst+nbitsd
1034  else
1035  call g2_sbytec(cpack,1,iofst,1)
1036  iofst=iofst+1
1037  call g2_sbytec(cpack,iabs(ival2),iofst,nbitsd-1)
1038  iofst=iofst+nbitsd-1
1039  endif
1040  endif
1041  ! pack overall min of spatial differences
1042  if (minsd.ge.0) then
1043  call g2_sbytec(cpack,minsd,iofst,nbitsd)
1044  iofst=iofst+nbitsd
1045  else
1046  call g2_sbytec(cpack,1,iofst,1)
1047  iofst=iofst+1
1048  call g2_sbytec(cpack,iabs(minsd),iofst,nbitsd-1)
1049  iofst=iofst+nbitsd-1
1050  endif
1051  endif
1052  !print *,'SDp ',ival1,ival2,minsd,nbitsd
1053  endif ! end of spatial diff section
1054 
1055  ! Expand non-missing data values to original grid.
1056  miss1=minval(jfld(1:nonmiss))-1
1057  miss2=miss1-1
1058  n=0
1059  do j=1,ndpts
1060  if ( ifldmiss(j).eq.0 ) then
1061  n=n+1
1062  ifld(j)=jfld(n)
1063  elseif ( ifldmiss(j).eq.1 ) then
1064  ifld(j)=miss1
1065  elseif ( ifldmiss(j).eq.2 ) then
1066  ifld(j)=miss2
1067  endif
1068  enddo
1069  if(ndpts<2) simple_alg=.true.
1070 
1071  ! Determine Groups to be used.
1072  if ( simple_alg ) then
1073  ! set group length to 10 : calculate number of groups
1074  ! and length of last group
1075  ngroups=ndpts/10
1076  glen(1:ngroups)=10
1077  itemp=mod(ndpts,10)
1078  if (itemp.ne.0) then
1079  ngroups=ngroups+1
1080  glen(ngroups)=itemp
1081  endif
1082  else
1083  ! Use Dr. Glahn's algorithm for determining grouping.
1084  !
1085  minpk=10
1086  inc=1
1087  maxgrps=(ndpts/minpk)+1
1088  allocate(jmin(maxgrps))
1089  allocate(jmax(maxgrps))
1090  allocate(lbit(maxgrps))
1091  call pack_gp(ifld,ndpts,missopt,minpk,inc,miss1,miss2, &
1092  jmin,jmax,lbit,glen,maxgrps,ngroups,ibit,jbit, &
1093  kbit,novref,lbitref,ier)
1094  !print *,'SAGier = ',ier,ibit,jbit,kbit,novref,lbitref
1095  do ng=1,ngroups
1096  glen(ng)=glen(ng)+novref
1097  enddo
1098  deallocate(jmin)
1099  deallocate(jmax)
1100  deallocate(lbit)
1101  endif
1102 
1103  ! For each group, find the group's reference value (min)
1104  ! and the number of bits needed to hold the remaining values
1105  n=1
1106  do ng=1,ngroups
1107  ! how many of each type?
1108  num0=count(ifldmiss(n:n+glen(ng)-1) .EQ. 0)
1109  num1=count(ifldmiss(n:n+glen(ng)-1) .EQ. 1)
1110  num2=count(ifldmiss(n:n+glen(ng)-1) .EQ. 2)
1111  if ( num0.eq.0 ) then ! all missing values
1112  if ( num1.eq.0 ) then ! all secondary missing
1113  gref(ng)=-2
1114  gwidth(ng)=0
1115  elseif ( num2.eq.0 ) then ! all primary missing
1116  gref(ng)=-1
1117  gwidth(ng)=0
1118  else ! both primary and secondary
1119  gref(ng)=0
1120  gwidth(ng)=1
1121  endif
1122  else ! contains some non-missing data
1123  ! find max and min values of group
1124  gref(ng)=huge(n)
1125  imax=-1*huge(n)
1126  j=n
1127  do lg=1,glen(ng)
1128  if ( ifldmiss(j).eq.0 ) then
1129  if (ifld(j).lt.gref(ng)) gref(ng)=ifld(j)
1130  if (ifld(j).gt.imax) imax=ifld(j)
1131  endif
1132  j=j+1
1133  enddo
1134  if (missopt.eq.1) imax=imax+1
1135  if (missopt.eq.2) imax=imax+2
1136  ! calc num of bits needed to hold data
1137  if ( gref(ng).ne.imax ) then
1138  temp=i1log2(imax-gref(ng))
1139  gwidth(ng)=ceiling(temp)
1140  else
1141  gwidth(ng)=0
1142  endif
1143  endif
1144  ! Subtract min from data
1145  j=n
1146  mtemp=2**gwidth(ng)
1147  do lg=1,glen(ng)
1148  if (ifldmiss(j).eq.0) then ! non-missing
1149  ifld(j)=ifld(j)-gref(ng)
1150  elseif (ifldmiss(j).eq.1) then ! primary missing
1151  ifld(j)=mtemp-1
1152  elseif (ifldmiss(j).eq.2) then ! secondary missing
1153  ifld(j)=mtemp-2
1154  endif
1155  j=j+1
1156  enddo
1157  ! increment fld array counter
1158  n=n+glen(ng)
1159  enddo
1160 
1161  ! Find max of the group references and calc num of bits needed
1162  ! to pack each groups reference value, then
1163  ! pack up group reference values
1164  !write(77,*)'GREFS: ',(gref(j),j=1,ngroups)
1165  igmax=maxval(gref(1:ngroups))
1166  if (missopt.eq.1) igmax=igmax+1
1167  if (missopt.eq.2) igmax=igmax+2
1168  if (igmax.ne.0) then
1169  temp=i1log2(igmax)
1170  nbitsgref=ceiling(temp)
1171  ! restet the ref values of any "missing only" groups.
1172  mtemp=2**nbitsgref
1173  do j=1,ngroups
1174  if (gref(j).eq.-1) gref(j)=mtemp-1
1175  if (gref(j).eq.-2) gref(j)=mtemp-2
1176  enddo
1177  call g2_sbytesc(cpack,gref,iofst,nbitsgref,0,ngroups)
1178  itemp=nbitsgref*ngroups
1179  iofst=iofst+itemp
1180  ! Pad last octet with Zeros, if necessary,
1181  if (mod(itemp,8).ne.0) then
1182  left=8-mod(itemp,8)
1183  call g2_sbytec(cpack,zero,iofst,left)
1184  iofst=iofst+left
1185  endif
1186  else
1187  nbitsgref=0
1188  endif
1189 
1190  ! Find max/min of the group widths and calc num of bits needed
1191  ! to pack each groups width value, then
1192  ! pack up group width values
1193  !write(77,*)'GWIDTHS: ',(gwidth(j),j=1,ngroups)
1194  iwmax=maxval(gwidth(1:ngroups))
1195  ngwidthref=minval(gwidth(1:ngroups))
1196  if (iwmax.ne.ngwidthref) then
1197  temp=i1log2(iwmax-ngwidthref)
1198  nbitsgwidth=ceiling(temp)
1199  do i=1,ngroups
1200  gwidth(i)=gwidth(i)-ngwidthref
1201  enddo
1202  call g2_sbytesc(cpack,gwidth,iofst,nbitsgwidth,0,ngroups)
1203  itemp=nbitsgwidth*ngroups
1204  iofst=iofst+itemp
1205  ! Pad last octet with Zeros, if necessary,
1206  if (mod(itemp,8).ne.0) then
1207  left=8-mod(itemp,8)
1208  call g2_sbytec(cpack,zero,iofst,left)
1209  iofst=iofst+left
1210  endif
1211  else
1212  nbitsgwidth=0
1213  gwidth(1:ngroups)=0
1214  endif
1215 
1216  ! Find max/min of the group lengths and calc num of bits needed
1217  ! to pack each groups length value, then
1218  ! pack up group length values
1219  !write(77,*)'GLENS: ',(glen(j),j=1,ngroups)
1220  ilmax=maxval(glen(1:ngroups-1))
1221  nglenref=minval(glen(1:ngroups-1))
1222  if(ngroups>0) then
1223  nglenlast=glen(ngroups)
1224  else
1225  nglenlast=0
1226  endif
1227  if (ilmax.ne.nglenref) then
1228  temp=i1log2(ilmax-nglenref)
1229  nbitsglen=ceiling(temp)
1230  do i=1,ngroups-1
1231  glen(i)=glen(i)-nglenref
1232  enddo
1233  call g2_sbytesc(cpack,glen,iofst,nbitsglen,0,ngroups)
1234  itemp=nbitsglen*ngroups
1235  iofst=iofst+itemp
1236  ! Pad last octet with Zeros, if necessary,
1237  if (mod(itemp,8).ne.0) then
1238  left=8-mod(itemp,8)
1239  call g2_sbytec(cpack,zero,iofst,left)
1240  iofst=iofst+left
1241  endif
1242  else
1243  nbitsglen=0
1244  glen(1:ngroups)=0
1245  endif
1246 
1247  ! For each group, pack data values
1248  !write(77,*)'IFLDS: ',(ifld(j),j=1,ndpts)
1249  n=1
1250  ij=0
1251  do ng=1,ngroups
1252  glength=glen(ng)+nglenref
1253  if (ng.eq.ngroups ) glength=nglenlast
1254  grpwidth=gwidth(ng)+ngwidthref
1255  !write(77,*)'NGP ',ng,grpwidth,glength,gref(ng)
1256  if ( grpwidth.ne.0 ) then
1257  call g2_sbytesc(cpack,ifld(n),iofst,grpwidth,0,glength)
1258  iofst=iofst+(grpwidth*glength)
1259  endif
1260  do kk=1,glength
1261  ij=ij+1
1262  !write(77,*)'SAG ',ij,fld(ij),ifld(ij),gref(ng),bscale,rmin,dscale
1263  enddo
1264  n=n+glength
1265  enddo
1266  ! Pad last octet with Zeros, if necessary,
1267  if (mod(iofst,8).ne.0) then
1268  left=8-mod(iofst,8)
1269  call g2_sbytec(cpack,zero,iofst,left)
1270  iofst=iofst+left
1271  endif
1272  lcpack=iofst/8
1273  !
1274  if ( allocated(ifld) ) deallocate(ifld)
1275  if ( allocated(jfld) ) deallocate(jfld)
1276  if ( allocated(ifldmiss) ) deallocate(ifldmiss)
1277  if ( allocated(gref) ) deallocate(gref)
1278  if ( allocated(gwidth) ) deallocate(gwidth)
1279  if ( allocated(glen) ) deallocate(glen)
1280 
1281  ! Fill in ref value and number of bits in Template 5.2
1282  rmin4 = real(rmin, 4)
1283  call mkieee(rmin4,ref,1) ! ensure reference value is IEEE format
1284  iref=transfer(ref,iref)
1285  idrstmpl(1)=iref
1286  idrstmpl(4)=nbitsgref
1287  idrstmpl(5)=0 ! original data were reals
1288  idrstmpl(6)=1 ! general group splitting
1289  idrstmpl(10)=ngroups ! Number of groups
1290  idrstmpl(11)=ngwidthref ! reference for group widths
1291  idrstmpl(12)=nbitsgwidth ! num bits used for group widths
1292  idrstmpl(13)=nglenref ! Reference for group lengths
1293  idrstmpl(14)=1 ! length increment for group lengths
1294  idrstmpl(15)=nglenlast ! True length of last group
1295  idrstmpl(16)=nbitsglen ! num bits used for group lengths
1296  if (idrsnum.eq.3) then
1297  idrstmpl(18)=nbitsd/8 ! num bits used for extra spatial
1298  ! differencing values
1299  endif
1300 
1301 end subroutine misspack
subroutine misspack(fld, ndpts, idrsnum, idrstmpl, cpack, lcpack)
Pack up a data field using a GRIB2 algorithm with missing value management.
Definition: compack.F90:855
subroutine comunpack(cpack, len, lensec, idrsnum, idrstmpl, ndpts, fld, ier)
Unpack a data field that was packed using a complex packing algorithm as defined in the GRIB2 documen...
Definition: compack.F90:528
subroutine cmplxpack(fld, ndpts, idrsnum, idrstmpl, cpack, lcpack)
Pack up a data field using a complex packing algorithm.
Definition: compack.F90:43
subroutine compack(fld, ndpts, idrsnum, idrstmpl, cpack, lcpack)
Pack a data field with complex packing with or without spatial differences, defined in Data Represent...
Definition: compack.F90:89
subroutine g2_gbytesc(in, iout, iskip, nbits, nskip, n)
Extract arbitrary size big-endian integer values (up to 32 bits each) from a packed bit string.
Definition: g2bytes.F90:120
subroutine rdieee(rieee, a, num)
Copy array of 32-bit IEEE floating point values to local floating point representation.
Definition: g2bytes.F90:637
subroutine g2_gbytec(in, iout, iskip, nbits)
Extract one arbitrary size big-endian value (up to 32 bits) from a packed bit string into one element...
Definition: g2bytes.F90:21
subroutine mkieee(a, rieee, num)
Copy an array of real to an array of 32-bit IEEE floating points.
Definition: g2bytes.F90:685
subroutine g2_sbytec(out, in, iskip, nbits)
Put one arbitrary sized (up to 32 bits) value from an integer array, into a packed bit string,...
Definition: g2bytes.F90:306
subroutine g2_sbytesc(out, in, iskip, nbits, nskip, n)
Put arbitrary size (up to 32 bits each) integer values into a packed bit string in big-endian order.
Definition: g2bytes.F90:402
Define math functions used by compack(), simpack(), and misspack().
Definition: intmath.F90:22
subroutine pack_gp(IC, NXY, IS523, MINPK, INC, MISSP, MISSS, JMIN, JMAX, LBIT, NOV, NDG, LX, IBIT, JBIT, KBIT, NOVREF, LBITREF, IER)
This subroutine determines groups of variable size, but at least of size minpk, the associated max(JM...
Definition: pack_gp.f:116