NCEPLIBS-g2  3.4.5
compack.f
Go to the documentation of this file.
1 
5 
30 
31  subroutine compack(fld,ndpts,idrsnum,idrstmpl,cpack,lcpack)
32 
33  use intmath
34  implicit none
35  integer,intent(in) :: ndpts,idrsnum
36  real,intent(in) :: fld(ndpts)
37  character(len=1),intent(out) :: cpack(*)
38  integer,intent(inout) :: idrstmpl(*)
39  integer,intent(out) :: lcpack
40 
41  real :: bscale,dscale
42  integer :: j,iofst,imin,ival1,ival2,minsd,nbitsd,n
43  integer :: igmax,nbitsgref,left,iwmax,i,ilmax,kk,ij
44  integer :: ngwidthref,nbitsgwidth,nglenref,nglenlast
45  integer :: maxorig,nbitorig,isd,ngroups,itemp,minpk
46  integer :: kfildo,inc,maxgrps,missopt,miss1,miss2,lg
47  integer :: ibit,jbit,kbit,novref,lbitref,ier,ng,imax
48  integer :: nbitsglen
49  real(4) :: ref,rmin4
50  real(8) :: rmin,rmax
51 
52  integer(4) :: iref
53  integer,allocatable :: ifld(:)
54  integer,allocatable :: jmin(:),jmax(:),lbit(:)
55  integer,parameter :: zero=0
56  integer,allocatable :: gref(:),gwidth(:),glen(:)
57  integer :: glength,grpwidth
58  logical :: simple_alg
59 
60  simple_alg = .false.
61 
62  bscale=2.0**real(-idrstmpl(2))
63  dscale=10.0**real(idrstmpl(3))
64 !
65 ! Find max and min values in the data
66 !
67  if(ndpts>0) then
68  rmax=fld(1)
69  rmin=fld(1)
70  else
71  rmax=1.0
72  rmin=1.0
73  endif
74  do j=2,ndpts
75  if (fld(j).gt.rmax) rmax=fld(j)
76  if (fld(j).lt.rmin) rmin=fld(j)
77  enddo
78 !
79 ! If max and min values are not equal, pack up field.
80 ! If they are equal, we have a constant field, and the reference
81 ! value (rmin) is the value for each point in the field and
82 ! set nbits to 0.
83 !
84  multival: if (rmin.ne.rmax) then
85  iofst=0
86  allocate(ifld(ndpts))
87  allocate(gref(ndpts))
88  allocate(gwidth(ndpts))
89  allocate(glen(ndpts))
90  !
91  ! Scale original data
92  !
93  if (idrstmpl(2).eq.0) then ! No binary scaling
94  imin=nint(rmin*dscale)
95  !imax=nint(rmax*dscale)
96  rmin=real(imin)
97  do j=1,ndpts
98  ifld(j)=max(0,nint(fld(j)*dscale)-imin)
99  enddo
100  else ! Use binary scaling factor
101  rmin=rmin*dscale
102  !rmax=rmax*dscale
103  do j=1,ndpts
104  ifld(j)=max(0,nint(((fld(j)*dscale)-rmin)*bscale))
105  enddo
106  endif
107  !
108  ! Calculate Spatial differences, if using DRS Template 5.3
109  !
110  alg3: if (idrsnum.eq.3) then ! spatial differences
111  if (idrstmpl(17).ne.1.and.idrstmpl(17).ne.2) idrstmpl(17)=2
112  if (idrstmpl(17).eq.1) then ! first order
113  ival1=ifld(1)
114  if(ival1<0) then
115  print *,'G2: negative ival1',ival1
116  stop 101
117  endif
118  do j=ndpts,2,-1
119  ifld(j)=ifld(j)-ifld(j-1)
120  enddo
121  ifld(1)=0
122  elseif (idrstmpl(17).eq.2) then ! second order
123  ival1=ifld(1)
124  ival2=ifld(2)
125  if(ival1<0) then
126  print *,'G2: negative ival1',ival1
127  stop 11
128  endif
129  if(ival2<0) then
130  print *,'G2: negative ival2',ival2
131  stop 12
132  endif
133  do j=ndpts,3,-1
134  ifld(j)=ifld(j)-(2*ifld(j-1))+ifld(j-2)
135  enddo
136  ifld(1)=0
137  ifld(2)=0
138  endif
139  !
140  ! subtract min value from spatial diff field
141  !
142  isd=idrstmpl(17)+1
143  minsd=minval(ifld(isd:ndpts))
144  do j=isd,ndpts
145  ifld(j)=ifld(j)-minsd
146  enddo
147  !
148  ! find num of bits need to store minsd and add 1 extra bit
149  ! to indicate sign
150  !
151  nbitsd=i1log2(abs(minsd))+1
152  !
153  ! find num of bits need to store ifld(1) ( and ifld(2)
154  ! if using 2nd order differencing )
155  !
156  maxorig=ival1
157  if (idrstmpl(17).eq.2.and.ival2.gt.ival1) maxorig=ival2
158  nbitorig=i1log2(maxorig)+1
159  if (nbitorig.gt.nbitsd) nbitsd=nbitorig
160  ! increase number of bits to even multiple of 8 ( octet )
161  if (mod(nbitsd,8).ne.0) nbitsd=nbitsd+(8-mod(nbitsd,8))
162  !
163  ! Store extra spatial differencing info into the packed
164  ! data section.
165  !
166  if (nbitsd.ne.0) then
167  ! pack first original value
168  if (ival1.ge.0) then
169  call g2_sbytec(cpack,ival1,iofst,nbitsd)
170  iofst=iofst+nbitsd
171  else
172  call g2_sbytec(cpack,1,iofst,1)
173  iofst=iofst+1
174  call g2_sbytec(cpack,iabs(ival1),iofst,nbitsd-1)
175  iofst=iofst+nbitsd-1
176  endif
177  if (idrstmpl(17).eq.2) then
178  ! pack second original value
179  if (ival2.ge.0) then
180  call g2_sbytec(cpack,ival2,iofst,nbitsd)
181  iofst=iofst+nbitsd
182  else
183  call g2_sbytec(cpack,1,iofst,1)
184  iofst=iofst+1
185  call g2_sbytec(cpack,iabs(ival2),iofst,nbitsd-1)
186  iofst=iofst+nbitsd-1
187  endif
188  endif
189  ! pack overall min of spatial differences
190  if (minsd.ge.0) then
191  call g2_sbytec(cpack,minsd,iofst,nbitsd)
192  iofst=iofst+nbitsd
193  else
194  call g2_sbytec(cpack,1,iofst,1)
195  iofst=iofst+1
196  call g2_sbytec(cpack,iabs(minsd),iofst,nbitsd-1)
197  iofst=iofst+nbitsd-1
198  endif
199  endif
200  !print *,'SDp ',ival1,ival2,minsd,nbitsd
201  endif alg3 ! end of spatial diff section
202  !
203  ! Determine Groups to be used.
204  !
205  simplealg: if ( simple_alg ) then
206  ! set group length to 10 : calculate number of groups
207  ! and length of last group
208  print *,'G2: use simple algorithm'
209  ngroups=ndpts/10
210  glen(1:ngroups)=10
211  itemp=mod(ndpts,10)
212  if (itemp.ne.0) then
213  ngroups=ngroups+1
214  glen(ngroups)=itemp
215  endif
216  else
217  ! Use Dr. Glahn's algorithm for determining grouping.
218  !
219  kfildo=6
220  minpk=10
221  inc=1
222  maxgrps=((ndpts+minpk-1)/minpk)
223  allocate(jmin(maxgrps))
224  allocate(jmax(maxgrps))
225  allocate(lbit(maxgrps))
226  missopt=0
227  call pack_gp(kfildo,ifld,ndpts,missopt,minpk,inc,miss1,miss2,
228  & jmin,jmax,lbit,glen,maxgrps,ngroups,ibit,jbit,
229  & kbit,novref,lbitref,ier)
230  if(ier/=0) then
231  ! Dr. Glahn's algorithm failed; use simple packing method instead.
232  1099 format('G2: fall back to simple algorithm (glahn ier=',i0,&
233  & ')')
234  print 1099,ier
235  ngroups=ndpts/10
236  glen(1:ngroups)=10
237  itemp=mod(ndpts,10)
238  if (itemp.ne.0) then
239  ngroups=ngroups+1
240  glen(ngroups)=itemp
241  endif
242  elseif(ngroups<1) then
243  ! Dr. Glahn's algorithm failed; use simple packing method instead.
244  print *,'Glahn algorithm failed; use simple packing'
245  ngroups=ndpts/10
246  glen(1:ngroups)=10
247  itemp=mod(ndpts,10)
248  if (itemp.ne.0) then
249  ngroups=ngroups+1
250  glen(ngroups)=itemp
251  endif
252  else
253 !print *,'SAGier = ',ier,ibit,jbit,kbit,novref,lbitref
254  do ng=1,ngroups
255  glen(ng)=glen(ng)+novref
256  enddo
257  deallocate(jmin)
258  deallocate(jmax)
259  deallocate(lbit)
260  endif
261  endif simplealg
262  !
263  ! For each group, find the group's reference value
264  ! and the number of bits needed to hold the remaining values
265  !
266  n=1
267  do ng=1,ngroups
268  ! find max and min values of group
269  gref(ng)=ifld(n)
270  imax=ifld(n)
271  j=n+1
272  do lg=2,glen(ng)
273  if (ifld(j).lt.gref(ng)) gref(ng)=ifld(j)
274  if (ifld(j).gt.imax) imax=ifld(j)
275  j=j+1
276  enddo
277  ! calc num of bits needed to hold data
278  if ( gref(ng).ne.imax ) then
279  gwidth(ng)=i1log2(imax-gref(ng))
280  else
281  gwidth(ng)=0
282  endif
283  ! Subtract min from data
284  j=n
285  do lg=1,glen(ng)
286  ifld(j)=ifld(j)-gref(ng)
287  j=j+1
288  enddo
289  ! increment fld array counter
290  n=n+glen(ng)
291  enddo
292  !
293  ! Find max of the group references and calc num of bits needed
294  ! to pack each groups reference value, then
295  ! pack up group reference values
296  !
297  !write(77,*)'GREFS: ',(gref(j),j=1,ngroups)
298  igmax=maxval(gref(1:ngroups))
299  if (igmax.ne.0) then
300  nbitsgref=i1log2(igmax)
301  call g2_sbytesc(cpack,gref,iofst,nbitsgref,0,ngroups)
302  itemp=nbitsgref*ngroups
303  iofst=iofst+itemp
304  if (mod(itemp,8).ne.0) then
305  left=8-mod(itemp,8)
306  call g2_sbytec(cpack,zero,iofst,left)
307  iofst=iofst+left
308  endif
309  else
310  nbitsgref=0
311  endif
312  !
313  ! Find max/min of the group widths and calc num of bits needed
314  ! to pack each groups width value, then
315  ! pack up group width values
316  !
317  !write(77,*)'GWIDTHS: ',(gwidth(j),j=1,ngroups)
318  iwmax=maxval(gwidth(1:ngroups))
319  ngwidthref=minval(gwidth(1:ngroups))
320  if (iwmax.ne.ngwidthref) then
321  nbitsgwidth=i1log2(iwmax-ngwidthref)
322  do i=1,ngroups
323  gwidth(i)=gwidth(i)-ngwidthref
324  if(gwidth(i)<0) then
325  write(0,*) 'i,gw,ngw=',i,gwidth(i),ngwidthref
326  stop 9
327  endif
328  enddo
329  call g2_sbytesc(cpack,gwidth,iofst,nbitsgwidth,0,ngroups)
330  itemp=nbitsgwidth*ngroups
331  iofst=iofst+itemp
332  ! Pad last octet with Zeros, if necessary,
333  if (mod(itemp,8).ne.0) then
334  left=8-mod(itemp,8)
335  call g2_sbytec(cpack,zero,iofst,left)
336  iofst=iofst+left
337  endif
338  else
339  nbitsgwidth=0
340  gwidth(1:ngroups)=0
341  endif
342  !
343  ! Find max/min of the group lengths and calc num of bits needed
344  ! to pack each groups length value, then
345  ! pack up group length values
346  !
347  !write(77,*)'GLENS: ',(glen(j),j=1,ngroups)
348  ilmax=maxval(glen(1:ngroups-1))
349  nglenref=minval(glen(1:ngroups-1))
350  nglenlast=glen(ngroups)
351  if (ilmax.ne.nglenref) then
352  nbitsglen=i1log2(ilmax-nglenref)
353  do i=1,ngroups-1
354  glen(i)=glen(i)-nglenref
355  if(glen(i)<0) then
356  write(0,*) 'i,glen(i) = ',i,glen(i)
357  stop 23
358  endif
359  enddo
360  call g2_sbytesc(cpack,glen,iofst,nbitsglen,0,ngroups)
361  itemp=nbitsglen*ngroups
362  iofst=iofst+itemp
363  ! Pad last octet with Zeros, if necessary,
364  if (mod(itemp,8).ne.0) then
365  left=8-mod(itemp,8)
366  call g2_sbytec(cpack,zero,iofst,left)
367  iofst=iofst+left
368  endif
369  else
370  nbitsglen=0
371  glen(1:ngroups)=0
372  endif
373  !
374  ! For each group, pack data values
375  !
376  !write(77,*)'IFLDS: ',(ifld(j),j=1,ndpts)
377  n=1
378  ij=0
379  do ng=1,ngroups
380  glength=glen(ng)+nglenref
381  if (ng.eq.ngroups ) glength=nglenlast
382  grpwidth=gwidth(ng)+ngwidthref
383  !write(77,*)'NGP ',ng,grpwidth,glength,gref(ng)
384  if ( grpwidth.ne.0 ) then
385  call g2_sbytesc(cpack,ifld(n),iofst,grpwidth,0,glength)
386  iofst=iofst+(grpwidth*glength)
387  endif
388  do kk=1,glength
389  ij=ij+1
390  !write(77,*)'SAG ',ij,fld(ij),ifld(ij),gref(ng),bscale,rmin,dscale
391  enddo
392  n=n+glength
393  enddo
394  ! Pad last octet with Zeros, if necessary,
395  if (mod(iofst,8).ne.0) then
396  left=8-mod(iofst,8)
397  call g2_sbytec(cpack,zero,iofst,left)
398  iofst=iofst+left
399  endif
400  lcpack=iofst/8
401  !
402  if ( allocated(ifld) ) deallocate(ifld)
403  if ( allocated(gref) ) deallocate(gref)
404  if ( allocated(gwidth) ) deallocate(gwidth)
405  if ( allocated(glen) ) deallocate(glen)
406  else ! Constant field ( max = min )
407  lcpack=0
408  nbitsgref=0
409  ngroups=0
410  ngwidthref=0
411  nbitsgwidth=0
412  nglenref=0
413  nglenlast=0
414  nbitsglen=0
415  nbitsd=0
416  endif multival
417 
418 !
419 ! Fill in ref value and number of bits in Template 5.2
420 !
421  rmin4 = rmin
422  call mkieee(rmin4,ref,1) ! ensure reference value is IEEE format
423 ! call g2_gbytec(ref,idrstmpl(1),0,32)
424  iref=transfer(ref,iref)
425  idrstmpl(1)=iref
426  idrstmpl(4)=nbitsgref
427  idrstmpl(5)=0 ! original data were reals
428  idrstmpl(6)=1 ! general group splitting
429  idrstmpl(7)=0 ! No internal missing values
430  idrstmpl(8)=0 ! Primary missing value
431  idrstmpl(9)=0 ! secondary missing value
432  idrstmpl(10)=ngroups ! Number of groups
433  idrstmpl(11)=ngwidthref ! reference for group widths
434  idrstmpl(12)=nbitsgwidth ! num bits used for group widths
435  idrstmpl(13)=nglenref ! Reference for group lengths
436  idrstmpl(14)=1 ! length increment for group lengths
437  idrstmpl(15)=nglenlast ! True length of last group
438  idrstmpl(16)=nbitsglen ! num bits used for group lengths
439  if (idrsnum.eq.3) then
440  idrstmpl(18)=nbitsd/8 ! num bits used for extra spatial
441  ! differencing values
442  endif
443 
444  end
g2_sbytesc
subroutine g2_sbytesc(OUT, IN, ISKIP, NBYTE, NSKIP, N)
This subrountine is to put arbitrary size values into a packed bit string, taking the low order bits ...
Definition: g2_gbytesc.f:115
intmath::i1log2
Definition: intmath.f:33
g2_sbytec
subroutine g2_sbytec(OUT, IN, ISKIP, NBYTE)
This subrountine is to put arbitrary size values into a packed bit string, taking the low order bits ...
Definition: g2_gbytesc.f:39
compack
subroutine compack(fld, ndpts, idrsnum, idrstmpl, cpack, lcpack)
This subroutine packs up a data field.
Definition: compack.f:32
mkieee
subroutine mkieee(a, rieee, num)
This subroutine stores a list of real values in 32-bit IEEE floating point format.
Definition: mkieee.f:17
intmath
This module defines integer math functions used by other programs.
Definition: intmath.f:22
pack_gp
subroutine pack_gp(KFILDO, 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:155