SUBROUTINE GET_BITS(IBM,SGDS,LEN,MG,G,ISCALE,GROUND,GMIN,GMAX,NBIT) INTERFACE SUBROUTINE FNDBIT ( rmin, rmax, rdb, nmbts, iscale, iret ) END SUBROUTINE fndbit END INTERFACE !$$$ SUBPROGRAM DOCUMENTATION BLOCK ! SUBPROGRAM: GET_BITS COMPUTE NUMBER OF BITS AND ROUND FIELD. ! PRGMMR: IREDELL ORG: W/NP23 DATE: 92-10-31 ! ABSTRACT: THE NUMBER OF BITS REQUIRED TO PACK A GIVEN FIELD ! AT A PARTICULAR DECIMAL SCALING IS COMPUTED USING THE FIELD RANGE. ! THE FIELD IS ROUNDED OFF TO THE DECIMAL SCALING FOR PACKING. ! THE MINIMUM AND MAXIMUM ROUNDED FIELD VALUES ARE ALSO RETURNED. ! GRIB BITMAP MASKING FOR VALID DATA IS OPTIONALLY USED. ! PROGRAM HISTORY LOG: ! 92-10-31 IREDELL ! 95-04-14 BALDWIN - MODIFY FOLLOWING KEITH BRILL'S CODE ! TO USE SIG DIGITS TO COMPUTE DE! SCALE ! USAGE: CALL GET_BITS(IBM,ISGDS,LEN,MG,G,ISCALE,GROUND,GMIN,GMAX,NBIT) ! INPUT ARGUMENT LIST: ! IBM - INTEGER BITMAP FLAG (=0 FOR NO BITMAP) ! SGDS - MAXIMUM SIGNIFICANT DIGITS TO KEEP ! (E.G. SGDS=3.0 KEEPS 3 SIGNIFICANT DIGITS) ! OR BINARY PRECISION IF <0 ! (E.G. SGDS=-2.0 KEEPS FIELD TO NEAREST 1/4 ! -3.0 " " 1/8 ! 2**SGDS PRECISION) ! LEN - INTEGER LENGTH OF THE FIELD AND BITMAP ! MG - INTEGER (LEN) BITMAP IF IBM=1 (0 TO SKIP, 1 TO KEEP) ! G - REAL (LEN) FIELD ! OUTPUT ARGUMENT LIST: ! ISCALE - INTEGER DECIMAL SCALING ! GROUND - REAL (LEN) FIELD ROUNDED TO DECIMAL SCALING ! GMIN - REAL MINIMUM VALID ROUNDED FIELD VALUE ! GMAX - REAL MAXIMUM VALID ROUNDED FIELD VALUE ! NBIT - INTEGER NUMBER OF BITS TO PACK ! SUBPROGRAMS CALLED: ! ISRCHNE - FIND FIRST VALUE IN AN ARRAY NOT EQUAL TO TARGET VALUE ! ATTRIBUTES: ! LANGUAGE: FORTRAN !$$$ DIMENSION MG(LEN),G(LEN),GROUND(LEN) ! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ! DETERMINE EXTREMES WHERE BITMAP IS ON IF(IBM.EQ.0) THEN GMAX=MAXVAL(G) GMIN=MINVAL(G) ELSE I1=0 DO I=1,LEN IF(MG(I).NE.0.AND.I1.EQ.0) I1=I ENDDO IF(I1.GT.0.AND.I1.LE.LEN) THEN GMAX=G(I1) GMIN=G(I1) DO I=I1+1,LEN IF(MG(I).NE.0) THEN GMAX=MAX(GMAX,G(I)) GMIN=MIN(GMIN,G(I)) ENDIF ENDDO ELSE GMAX=0. GMIN=0. ENDIF ENDIF CALL FNDBIT ( GMIN, GMAX, SGDS, NBIT, ISCALE, IRETT) ! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - RETURN END SUBROUTINE FNDBIT ( rmin, rmax, rdb, nmbts, iscale, iret ) ! *********************************************************************** ! FNDBIT * ! * ! This subroutine computes the number of packing bits given the * ! maximum number of significant digits to preserve or the binary * ! precision to store the data. The binary precision is given as a * ! negative integer, ISCALE will always be zero in this case. * ! * ! The binary precision translates as follows: * ! -1 => store data to nearest 1/2 * ! -2 => store data to nearest 1/4 * ! -3 => store data to nearest 1/8 * ! * ! Note that a fractional number of significant digits is allowed. * ! * ! FNDBIT ( AMIN, AMAX, RDB, NBITS, ISCALE, IRET ) * ! * ! Input parameters: * ! AMIN REAL Minimum value * ! AMAX REAL Maximum value * ! RDB REAL Maximum # of significant digits * ! OR binary precision if < 0 * ! * ! Output parameters: * ! NBITS INTEGER Number of bits for packing * ! ISCALE INTEGER Power of 10 scaling to use * ! IRET INTEGER Return code * ! 0 = normal return * ! * * ! Log: * ! K. Brill/NMC 06/92 * ! K. Brill/EMC 12/95 Added binary precision * ! M. Baldwin 10/96 Added fix for negative nmbts ! *********************************************************************** ! DATA rln2/0.69314718/ !----------------------------------------------------------------------- iret = 0 icnt = 0 iscale = 0 range = rmax - rmin IF ( range .le. 0.00 ) THEN nmbts = 8 RETURN END IF ! IF ( rdb .eq. 0.0 ) THEN nmbts = 8 RETURN ELSE IF ( rdb .gt. 0.0 ) THEN ipo = INT (ALOG10 ( range )) IF ( range .lt. 1.00 ) ipo = ipo - 1 po = float(ipo) - rdb + 1. iscale = - INT ( po ) rr = range * 10. ** ( -po ) nmbts = INT ( ALOG ( rr ) / rln2 ) + 1 ELSE ibin = NINT ( -rdb ) rng2 = range * 2. ** ibin nmbts = INT ( ALOG ( rng2 ) / rln2 ) + 1 END IF ! IF(NMBTS.LE.0) THEN NMBTS=0 IF(ABS(RMIN).GE.1.) THEN ISCALE=-INT(ALOG10(ABS(RMIN))) ELSE IF (ABS(RMIN).LT.1.0.AND.ABS(RMIN).GT.0.0) THEN ISCALE=-INT(ALOG10(ABS(RMIN)))+1 ELSE ISCALE=0 ENDIF ENDIF RETURN END