Skip to content
Snippets Groups Projects
decompress.f90 8.45 KiB
Newer Older
  • Learn to ignore specific revisions
  • !-----------------------------------------------------------------
    !--------------- special set of characters for RCS information
    !-----------------------------------------------------------------
    ! $Source$ $Revision$ $Date$
    !-----------------------------------------------------------------
    SUBROUTINE GET_COMPHEADER(KTAB,SIZEKTAB,KNBELT,KTYPECOD)
    
    INTEGER, INTENT(IN) :: SIZEKTAB
    INTEGER(KIND=8), DIMENSION(SIZEKTAB), INTENT(IN) :: KTAB
    INTEGER, INTENT(OUT) :: KNBELT    ! size of decompressed array
    INTEGER, INTENT(OUT) :: KTYPECOD  ! code for compression type
    
    CHARACTER(LEN=8) :: STRKEY
    
    INTEGER :: INTCHAR
    INTEGER :: JI
    
    CALL SET_EXTRACTIDX(0,0)
    ! extract string header 
    DO JI=1,8
      CALL EXTRACT_BBUFF(KTAB,8,INTCHAR)
      STRKEY(JI:JI) = CHAR(INTCHAR)
    END DO
    
    ! Treat array if it is compressed
    IF (STRKEY == 'COMPRESS') THEN
      CALL EXTRACT_BBUFF(KTAB,32,KTYPECOD)
      CALL EXTRACT_BBUFF(KTAB,32,KNBELT)
    ELSE
      KNBELT    =-1
      KTYPECOD = 0
    END IF
    
    END SUBROUTINE GET_COMPHEADER
    
    SUBROUTINE DECOMPRESS_FIELD(XTAB,NBELT,COMPTAB,NBCOMPELT,CODINGTYPE)
    USE MODD_COMPPAR
    USE MODE_SEARCHGRP
    
    IMPLICIT NONE 
    INTEGER,                                INTENT(IN)  :: NBELT 
    INTEGER,                                INTENT(IN)  :: NBCOMPELT 
    REAL   (KIND=8),DIMENSION(NBELT),TARGET,INTENT(OUT) :: XTAB
    INTEGER(KIND=8),DIMENSION(NBCOMPELT),   INTENT(IN)  :: COMPTAB
    INTEGER,                                INTENT(IN)  :: CODINGTYPE
    
    INTEGER,DIMENSION(:), ALLOCATABLE  :: ITAB
    LOGICAL,DIMENSION(:), ALLOCATABLE  :: GMASK
    
    REAL :: XREF, XCOEFF
    INTEGER :: INBLEV
    INTEGER :: ILEVNBELT
    INTEGER :: JI
    INTEGER :: IND1, IND2
    INTEGER :: IDIMX,IDIMY
    INTEGER :: IEXTCOD
    REAL(KIND=8),DIMENSION(:),POINTER  :: XPTRTAB
    REAL :: XMIN,XMAX
    
    SELECT CASE (CODINGTYPE)
    CASE (JPCSTENCOD)
      CALL EXTRACT_BBUFF(COMPTAB,32,XREF)
      XTAB(:) = XREF
    
    CASE (JPSOPENCOD)
      CALL EXTRACT_BBUFF(COMPTAB,32,IDIMX)
      CALL EXTRACT_BBUFF(COMPTAB,32,IDIMY)
      ILEVNBELT = IDIMX * IDIMY
      INBLEV = NBELT/(ILEVNBELT)
      ALLOCATE(ITAB(ILEVNBELT))
      DO JI=1,INBLEV
        IND1=(JI-1)*ILEVNBELT+1
        IND2=JI*ILEVNBELT
        XPTRTAB=>XTAB(IND1:IND2)
        IF (LPDEBUG) PRINT *,'######   Decompress(SOPENCOD) LEVEL ',JI,'######'
        CALL EXTRACT_BBUFF(COMPTAB,32,XREF)
        CALL EXTRACT_BBUFF(COMPTAB,32,XCOEFF)
        CALL EXTRACTINTARRAY(ITAB)
        CALL DECOMP_FOP(XPTRTAB,ITAB,XREF,XCOEFF)
      END DO
      
    CASE (JPEXTENCOD)
      CALL EXTRACT_BBUFF(COMPTAB,32,IDIMX)
      CALL EXTRACT_BBUFF(COMPTAB,32,IDIMY)
      ILEVNBELT = IDIMX * IDIMY
      INBLEV = NBELT/(ILEVNBELT)
      ALLOCATE(ITAB(ILEVNBELT))
      ALLOCATE(GMASK(ILEVNBELT))
      DO JI=1,INBLEV
    
        IF (LPDEBUG) PRINT *,'###### Decompress(EXTENCOD) LEVEL ',JI,'######'
        IND1=(JI-1)*ILEVNBELT+1
        IND2=JI*ILEVNBELT
        XPTRTAB=>XTAB(IND1:IND2)
        !
        CALL EXTRACT_BBUFF(COMPTAB,3,IEXTCOD)
        IF (IEXTCOD == JPOTHER) THEN
          CALL EXTRACT_BBUFF(COMPTAB,3,IEXTCOD)
          IEXTCOD = IEXTCOD + 8
        END IF
        IF (LPDEBUG) PRINT *, "IEXTCOD = ",IEXTCOD
        SELECT CASE(IEXTCOD)
        CASE(JPLOG)
          ! Conversion to log values of original data 0<=x<1
          CALL EXTRACT_BBUFF(COMPTAB,32,XREF)
          CALL EXTRACT_BBUFF(COMPTAB,32,XCOEFF)
          CALL EXTRACTINTARRAY(ITAB)
          GMASK(:) = .TRUE.
          WHERE (ITAB == 0)
            GMASK = .FALSE.
            XPTRTAB = 0.0
          END WHERE
          CALL DECOMP_FOP(XPTRTAB,ITAB,XREF,XCOEFF,GMASK,1)
          WHERE(GMASK)
            XPTRTAB = EXP(XPTRTAB)
          END WHERE
          
        CASE(JPCONST)
          ! constant value array
          CALL EXTRACT_BBUFF(COMPTAB,32,XREF)
          XPTRTAB(:) = XREF
          IF (LPDEBUG) PRINT *,"  CONST value=",XREF
    
        CASE(JP2VAL)
          ! 2 different values in array
          CALL EXTRACT_BBUFF(COMPTAB,32,XMIN)
          CALL EXTRACT_BBUFF(COMPTAB,32,XMAX)
          CALL EXTRACTINTARRAY(ITAB)
          WHERE (ITAB == 0)
            XPTRTAB = XMIN
          ELSEWHERE
            XPTRTAB = XMAX
          END WHERE
          IF (LPDEBUG) PRINT *,"  2 values:",XMIN,XMAX
          
        CASE(JP3VAL)
          ! 3 different values in array
          CALL EXTRACT_BBUFF(COMPTAB,32,XMIN)
          CALL EXTRACT_BBUFF(COMPTAB,32,XREF)
          CALL EXTRACT_BBUFF(COMPTAB,32,XMAX)
          CALL EXTRACTINTARRAY(ITAB)
          WHERE (ITAB == 0)
            XPTRTAB = XMIN
          ELSEWHERE
            XPTRTAB = XREF
          END WHERE
          WHERE (ITAB == 2) XPTRTAB = XMAX
          IF (LPDEBUG) PRINT *,"  3 values:",XMIN,XREF,XMAX
    
        CASE(JPNORM)
          ! same as JPSOPENCOD
          CALL EXTRACT_BBUFF(COMPTAB,32,XREF)
          CALL EXTRACT_BBUFF(COMPTAB,32,XCOEFF)
          CALL EXTRACTINTARRAY(ITAB)
          CALL DECOMP_FOP(XPTRTAB,ITAB,XREF,XCOEFF)
          IF (LPDEBUG) PRINT *,"  normal, XREF/XCOEFF = ",XREF,XCOEFF 
    
        CASE(JPMINEXCL)
          ! Min value is isolated
          CALL EXTRACT_BBUFF(COMPTAB,32,XMIN)
          CALL EXTRACT_BBUFF(COMPTAB,32,XREF)
          CALL EXTRACT_BBUFF(COMPTAB,32,XCOEFF)
          CALL EXTRACTINTARRAY(ITAB)
          GMASK(:) = .TRUE.
          WHERE (ITAB == 0)
            GMASK = .FALSE.
            XPTRTAB = XMIN
          END WHERE
          CALL DECOMP_FOP(XPTRTAB,ITAB,XREF,XCOEFF,GMASK,1)
          IF (LPDEBUG) PRINT *,"  Min exclus, MIN/XREF/XCOEFF = ",XMIN,XREF,XCOEFF
    
        CASE(JPMAXEXCL)
          ! Max value is isolated
          CALL EXTRACT_BBUFF(COMPTAB,32,XMAX)
          CALL EXTRACT_BBUFF(COMPTAB,32,XREF)
          CALL EXTRACT_BBUFF(COMPTAB,32,XCOEFF)
          CALL EXTRACTINTARRAY(ITAB)
          GMASK(:) = .TRUE.
          WHERE (ITAB == 65535)
            GMASK = .FALSE.
            XPTRTAB = XMAX
          END WHERE
          CALL DECOMP_FOP(XPTRTAB,ITAB,XREF,XCOEFF,GMASK,0)   
          IF (LPDEBUG) PRINT *,"  Max exclus, MAX/XREF/XCOEFF = ",XMAX,XREF,XCOEFF
    
        CASE(JPMINMAXEXCL)
          ! Min&Max value are isolated
          CALL EXTRACT_BBUFF(COMPTAB,32,XMIN)        
          CALL EXTRACT_BBUFF(COMPTAB,32,XMAX)
          CALL EXTRACT_BBUFF(COMPTAB,32,XREF)
          CALL EXTRACT_BBUFF(COMPTAB,32,XCOEFF)
          CALL EXTRACTINTARRAY(ITAB)
          GMASK(:) = .TRUE.
          WHERE (ITAB == 0)
            GMASK = .FALSE.
            XPTRTAB = XMIN
          END WHERE
          WHERE (ITAB == 65535)
            GMASK = .FALSE.
            XPTRTAB = XMAX
          END WHERE
          CALL DECOMP_FOP(XPTRTAB,ITAB,XREF,XCOEFF,GMASK,1)
          IF (LPDEBUG) PRINT *,"  Min et Max exclus, MIN/MAX/XREF/XCOEFF = ",&
               &XMIN,XMAX,XREF,XCOEFF
        END SELECT
      END DO
      
    CASE DEFAULT
      PRINT *,'Error in CODINGTYPE : program aborted'
      STOP
    END SELECT
    
    CONTAINS 
    
    SUBROUTINE DECOMP_FOP(PTAB,KTAB,PREF,PCOEFF,OMASK,KINDCOR)
    REAL(KIND=8), DIMENSION(:), INTENT(INOUT) :: PTAB 
    ! Attention: avec le compilateur PGF, utiliser INTENT(OUT) provoque une recopie
    ! complete du tableau dans PTAB (avec ecrasement possible des valeurs 
    ! presentes a l'appel de la procedure). Le phenomene est genant lorsque
    ! DECOMP_FOP ne calcule que sur une portion de PTAB (valeurs min et/ou max 
    ! sont presentes). En declarant PTAB en INOUT, les valeurs en entree de la routine
    ! sont conservees si elles n'ont pas ete modifiees.
    
    INTEGER,      DIMENSION(:), INTENT(IN) :: KTAB 
    REAL, INTENT(IN) :: PREF
    REAL, INTENT(IN) :: PCOEFF
    LOGICAL, DIMENSION(:),INTENT(IN),OPTIONAL :: OMASK
    INTEGER,INTENT(IN),OPTIONAL  :: KINDCOR ! 1 if Min value is isolated, 0 otherwise
    
    INTEGER :: INDCOR
    
    IF (.NOT. PRESENT(KINDCOR)) THEN
      INDCOR = 0
    ELSE
      INDCOR = KINDCOR
    END IF
      
    IF (PRESENT(OMASK)) THEN
      WHERE (OMASK)
        PTAB(:) = PCOEFF*(KTAB(:)-INDCOR)+PREF
      END WHERE
    ELSE
      IF (PCOEFF == 0.0) THEN
        PTAB(:) = PREF
      ELSE
        PTAB(:) = PCOEFF*KTAB(:)+PREF
      END IF
    END IF
    
    END SUBROUTINE DECOMP_FOP
    
    SUBROUTINE EXTRACTINTARRAY(KTAB)
    INTEGER,DIMENSION(:),INTENT(OUT) :: KTAB
    !
    ! COMPTAB, IDIMX and IDIMY  are defined in the calling routine
    !
    INTEGER :: NBGRP
    INTEGER :: IBE
    INTEGER :: CPT
    INTEGER :: JJ
    INTEGER :: ALONE
    INTEGER :: NBITCOD,IMIN
    INTEGER :: GELT
    INTEGER :: JELT
    INTEGER :: IEPS
    
    CALL EXTRACT_BBUFF(COMPTAB,32,NBGRP)
    !      PRINT *,'Nbre de groupes =',NBGRP
    CALL EXTRACT_BBUFF(COMPTAB,5,IBE)
    !      PRINT *,'Nbre de bits pour coder le nombre d''elements:',IBE
    CPT = 1
    DO JJ=1,NBGRP
      !      PRINT *,'Groupe ',JJ,' : '
      CALL EXTRACT_BBUFF(COMPTAB,1,ALONE)
      CALL EXTRACT_BBUFF(COMPTAB,16,IMIN)
      !      PRINT *,'IREF=',IMIN
      
      IF (ALONE == 1) THEN
        ! 1 seul elt dans le groupe
        !        PRINT *,'--> un seul element dans le groupe'
        KTAB(CPT)=IMIN
        CPT=CPT+1
      ELSE
        CALL EXTRACT_BBUFF(COMPTAB,4,NBITCOD)
        CALL EXTRACT_BBUFF(COMPTAB,IBE,GELT)
        !        PRINT *,'--> ',GELT,' elts, codage ecart sur ',nbitcod,'bits'
        IF (NBITCOD > 0) THEN
          DO JELT=1,GELT
            CALL EXTRACT_BBUFF(COMPTAB,NBITCOD,IEPS)
            KTAB(CPT) = IMIN+IEPS
            CPT=CPT+1
          END DO
        ELSE
          KTAB(CPT:CPT+GELT-1) = IMIN
          CPT = CPT+GELT
        END IF
      END IF
    END DO
    CALL INVERTCOL(KTAB,IDIMX,IDIMY)        
    END SUBROUTINE EXTRACTINTARRAY
    
    END SUBROUTINE DECOMPRESS_FIELD