Snippet Library
Module de compression sans perte flottant - Fortran | |
Type: Sample Code (HOWTO) |
Category: Other |
License: GNU General Public License |
Language: Other Language |
Description: J'ai implémenté ce module pour un logiciel d'évaluation génomique (genekit. V.Ducrocq). Ce module avait le double avantage de compresser les fichiers de données (format texte à l'origine) comportant plusieurs millions d'enregistrement mais également d'optimiser les communications entre les processus MPI. Il s'est avéré que le module était inutilisable pour les communications entre processus (déjà bien optimiser par les implémentations MPI existantes). J'ai implémenté ce module à partir de l'article : "Fast Lossless Compression of Scientific Floating-Point Data." Ratanaworabhan et al Le module implémente une classe principale CompressFPD64 pour l'interface de compression et de décompression et d'un ensemble de classe pour les prédictions (DataFilePredictorFPD, StridePredictorFPD, TwoStridePredictorFPD, FCMPredictorFPD) |
Versions Of This Snippet:
Snippet ID | Download Version | Date Posted | Author | Delete |
---|---|---|---|---|
2 | 1.0 | 2015-05-12 08:51 | Olivier Filangi |
Download a raw-text version of this code by clicking on “Download Version”
Latest Snippet Version: 1.0
! Author : Olivier Dot Filangi At Gmail[.]FR
! This module provide a set of datatype to manage a fast lossless compression of floating point dara.
! Reference : Fast Lossless Compression of Scientific Floating-Point Data. Ratanaworabhan et al
!
! Two classes of Predictors : DataFilePredictorFPD,StridePredictorFPD manage a prediction of value to compress data.
! The class CompressFPD64 manage the stream of compressed data
!
!
!
!
! Module COMPRESS_FLOATING_POINT_DATA de compression adapté aux fichiers de performances contenant des flottants
! Proprietes :
! 1) Utilisation d'un predicteur avec un historique ( = nombre de colonne pour un fichier)
! 2) XOR entre cette valeur et la valeur
! 3) sauvegarde du ZCL (zero count leading) + DIFF
!
!
! modification
! 24/06/2014 donnée membre "stream" du type CompressFPD64 pointe vers null à l'initialisation
!
module compress_fpd
implicit none
!#define DEBUG_MOD
#undef DEBUG_MOD
integer, parameter, private :: sp = selected_real_kind(6, 37)
integer, parameter, private :: dp = selected_real_kind(15, 307)
integer, parameter, private :: qp = selected_real_kind(33, 4931)
! Codage du Zero Count Leading sur 7 bits en double precision pour atteindre 64
integer , parameter :: NBITS_ZCL_DP = 7
integer , parameter :: NBITS_DP = 64
! Codage du Zero Count Leading sur 6 bits en double precision pour atteindre 32
integer , parameter :: NBITS_ZCL_SP = 6
integer , parameter :: NBITS_SP = 32
! Codage du ZCL sur 4 bits le nombre de zero est egale à 4*ZCL
integer , parameter :: NBITS_ZLC_4 = 4
! Codage du ZCL sur 4 bits le nombre de zero est egale à 8*ZCL
integer , parameter :: NBITS_ZLC_2 = 2
integer , parameter :: NBITS_ZLC_SELECT = NBITS_ZLC_4
type , public :: CompressFPD64
integer ,private :: BLOCK_SIZE_ALLOC = 100000000 ! taille du buffer
integer ,private :: nstream = 0 ! taille du buffer
integer(kind=8) ,dimension(:),pointer,public :: stream => null()
integer ,public :: idxstream = 0 ! index dans le tableau stream pour la prochaine insertion
integer ,private :: idxbitstream = -1 ! index dans l'entier courant pour la prochaine insertion
integer ,public :: nflottantTreated = 0 ! Nombre de flottant deja traité
contains
! allocation of new stream
procedure, public :: setcompress => set_CompressFPD64
! Prepare to uncompress a stream
procedure, public :: setuncompress => set_UncompressFPD64
! deallocation of stream
procedure, public :: release => release_CompressFPD64
! reinit all index keeping the current stream
procedure, public :: rewind
! Get ratio compression (number of integer coded/number of floatted point elt compressed)
procedure, public :: ratio
! Get information stream
procedure, public :: info => info_CompressFPD64
! resize the stream buffer
procedure, public :: resize_stream
! Add ZCL et DIFF information for simple and double precision in a binary stream
procedure, private :: encode_stream64
! retrieve ZCL et DIFF information for simple and double precision from a binary stream
procedure, private :: decode_stream64
procedure ,public :: init => init64
procedure ,public :: addstream => addstream64
procedure ,public :: getstream => getstream64
! Compress un ensemble de N (taille de l'historique) Valeurs double precision
procedure ,public :: compress64
! Uncompress un ensemble de N (taille de l'historique) Valeurs double precision
procedure ,public :: uncompress64
! Compress un ensemble de N (taille de l'historique) Valeurs simple precision
procedure ,public :: compress32
! Uncompress un ensemble de N (taille de l'historique) Valeurs simple precision
procedure ,public :: uncompress32
! convert the ZCL in the representation domaine 2 bits => 16 values (0,8,16,32)
procedure ,public :: getcode
procedure ,public :: getZCL
end type CompressFPD64
!!===================================================================================
!!
!! Predictor
type, abstract , public :: PredictorFPD
contains
procedure(subinit) ,deferred :: init
procedure(subrelease) ,deferred :: release
procedure(subrelease) ,deferred :: reset
procedure(functpred32),deferred :: predict32
procedure(functpred64),deferred :: predict64
procedure(subupdate32),deferred :: update32
procedure(subupdate64),deferred :: update64
end type PredictorFPD
abstract interface
subroutine subinit(this,nhist)
import PredictorFPD
class(PredictorFPD) , intent(inout) :: this
integer , intent(in) :: nhist
end subroutine subinit
subroutine subrelease(this)
import PredictorFPD
class(PredictorFPD) , intent(inout) :: this
end subroutine subrelease
function functpred32(this,hash,bidon) result(val)
import PredictorFPD
class(PredictorFPD) ,intent(in) :: this
integer ,intent(in) :: hash
integer(kind=8) :: val
real(kind=4) ,intent(in) :: bidon
end function functpred32
function functpred64(this,hash,bidon) result(val)
import PredictorFPD
class(PredictorFPD) ,intent(in) :: this
integer ,intent(in) :: hash
integer(kind=8) :: val
real(kind=8) ,intent(in) :: bidon
end function functpred64
subroutine subupdate32(this,hash,val_flot,val_int)
import PredictorFPD
class(PredictorFPD) , intent(inout) :: this
integer , intent(in) :: hash
real(kind=4) , intent(in) :: val_flot
integer(kind=8) , intent(in) :: val_int
end subroutine subupdate32
subroutine subupdate64(this,hash,val_flot,val_int)
import PredictorFPD
class(PredictorFPD) , intent(inout) :: this
integer , intent(in) :: hash
real(kind=8) , intent(in) :: val_flot
integer(kind=8) , intent(in) :: val_int
end subroutine subupdate64
end interface
type , extends(PredictorFPD), public :: DataFilePredictorFPD
! nombre de colonne (correspondant au nombre de colonne du fichier data)
integer ,private :: ncol
!stockage des anciennes valeurs par colonne
integer(kind=8) , dimension(:),allocatable ,private :: lastrecord
contains
procedure ,public :: init => datafile_init
procedure ,public :: release => datafile_release
procedure ,public :: reset => datafile_reset
procedure ,public :: predict32 => datafile_predict32
procedure ,public :: predict64 => datafile_predict64
procedure ,public :: update32 => datafile_update32
procedure ,public :: update64 => datafile_update64
end type DataFilePredictorFPD
type , extends(PredictorFPD) , public :: StridePredictorFPD
! rang du predicteur
integer ,private :: nhist
!stockage des anciennes valeurs
integer(kind=8) , dimension(:),allocatable ,private :: lastrecord
!stockage de la difference entre la valeur de lastrecord et la valeur precedente
real(kind=dp) , dimension(:),allocatable ,private :: stride
contains
procedure ,public :: init => stride_init
procedure ,public :: release => stride_release
procedure ,public :: reset => stride_reset
procedure ,public :: predict32 => stride_predict32
procedure ,public :: predict64 => stride_predict64
procedure ,public :: update32 => stride_update32
procedure ,public :: update64 => stride_update64
end type StridePredictorFPD
type , extends(PredictorFPD) , public :: TwoStridePredictorFPD
! rang du predicteur
integer ,private :: nhist
!stockage des anciennes valeurs
integer(kind=8) , dimension(:),allocatable ,private :: lastrecord
!stockage de la difference entre la valeur de lastrecord et la valeur precedente
real(kind=dp) , dimension(:),allocatable ,private :: stride1
real(kind=dp) , dimension(:),allocatable ,private :: stride2
contains
procedure ,public :: init => stride2_init
procedure ,public :: release => stride2_release
procedure ,public :: reset => stride2_reset
procedure ,public :: predict32 => stride2_predict32
procedure ,public :: predict64 => stride2_predict64
procedure ,public :: update32 => stride2_update32
procedure ,public :: update64 => stride2_update64
end type TwoStridePredictorFPD
type , extends(PredictorFPD) , public :: FCMPredictorFPD
! rang du predicteur
integer ,private :: order = 14 ! order of FCM
! integer ,private :: nhist
integer ,private :: k = 100 ! history size
!stockage des anciennes valeurs
integer(kind=8) , dimension(:,:),allocatable ,private :: history ! last record dim = order,nhist
integer ,private :: counter_context = 0
integer(kind=8) , dimension(:,:,:),allocatable ,private :: context ! => keep history dim k,order,nhist
integer(kind=8) , dimension(:,:) ,allocatable ,private :: valcontext ! => get index dim k,nhist
! real(kind=dp) , dimension(:,:) ,allocatable ,private :: stride
contains
procedure ,public :: init => fcm_init
procedure ,public :: release => fcm_release
procedure ,public :: reset => fcm_reset
procedure ,public :: predict32 => fcm_predict32
procedure ,public :: predict64 => fcm_predict64
procedure ,public :: update32 => fcm_update32
procedure ,public :: update64 => fcm_update64
end type FCMPredictorFPD
!!!! =========================== TEST SUBROUTINE =============================
public :: test_module_FPD
contains
!! *********************************************************
! simple prediction : la prediction est la derniere valeur rencontrée de la colonne
function fcm_predict64(this,hash,bidon) result(val)
class(FCMPredictorFPD) , intent(in) :: this
integer , intent(in) :: hash
real(kind=dp) , intent(in) :: bidon
integer(kind=8) :: val
real(kind=dp) :: val_flot
integer :: ihist,i,j
logical :: equal
ihist = 1 ! mod(hash,this%nhist+1)
!seek in the context the corresponding history to get a value
do i=1,this%k
equal=.true.
do j=1,this%order
if ( this%history(j,ihist) /= this%context(i,j,ihist) ) then
equal = .false.
exit
end if
end do
if (equal) then ! we find the corresponding history
val = this%valcontext(i,ihist)
return
end if
end do
!none context was found, return last context recorded...
val = this%valcontext(this%counter_context,ihist)
return
end function fcm_predict64
! simple prediction : la prediction est la derniere valeur rencontrée de la colonne
function fcm_predict32(this,hash,bidon) result(val)
class(FCMPredictorFPD) , intent(in) :: this
integer , intent(in) :: hash
real(kind=sp) , intent(in) :: bidon
integer(kind=8) :: val
integer :: ihist,i,j
logical :: equal
ihist = 1 ! mod(hash,this%nhist+1)
!seek in the context the corresponding history to get a value
do i=1,this%k
equal=.true.
do j=1,this%order
if ( this%history(j,ihist) /= this%context(i,j,ihist) ) then
equal = .false.
exit
end if
end do
if (equal) then ! we find the corresponding history
val = this%valcontext(i,ihist)
return
end if
end do
!none context was found, return last context recorded...
val = this%valcontext(this%counter_context,ihist)
end function fcm_predict32
!! *********************************************************
! simple prediction : la prediction est la derniere valeur rencontrée de la colonne
function datafile_predict64(this,hash,bidon) result(val)
class(DataFilePredictorFPD) , intent(in) :: this
integer , intent(in) :: hash
real(kind=dp) , intent(in) :: bidon
integer(kind=8) :: val
val = this%lastrecord(mod(hash,this%ncol)+1)
return
end function datafile_predict64
! simple prediction : la prediction est la derniere valeur rencontrée de la colonne
function datafile_predict32(this,hash,bidon) result(val)
class(DataFilePredictorFPD) , intent(in) :: this
integer , intent(in) :: hash
real(kind=sp) , intent(in) :: bidon
integer(kind=8) :: val
val = this%lastrecord(mod(hash,this%ncol)+1)
return
end function datafile_predict32
!! *********************************************************
! prediction stride : la prediction est la derniere valeur rencontrée de la colonne
! + la difference entre cette valeur et la valeur precedente de la colonne
function stride_predict64(this,hash,bidon) result(val)
class(StridePredictorFPD) , intent(in) :: this
integer , intent(in) :: hash
real(kind=dp) , intent(in) :: bidon
integer(kind=8) :: val
real(kind=dp) :: val_flot
val_flot = transfer(this%lastrecord(mod(hash,this%nhist)+1),val_flot)
val_flot = val_flot + this%stride(mod(hash,this%nhist)+1)
val = transfer(val_flot,val)
return
end function stride_predict64
function stride_predict32(this,hash,bidon) result(val)
class(StridePredictorFPD) , intent(in) :: this
integer , intent(in) :: hash
real(kind=sp) , intent(in) :: bidon
integer(kind=8) :: val
real(kind=sp) :: val_flot
val_flot = transfer(this%lastrecord(mod(hash,this%nhist)+1),val_flot)
val_flot = val_flot + this%stride(mod(hash,this%nhist)+1)
val = transfer(val_flot,val)
return
end function stride_predict32
!! *********************************************************
function stride2_predict64(this,hash,bidon) result(val)
class(TwoStridePredictorFPD) , intent(in) :: this
integer , intent(in) :: hash
real(kind=dp) , intent(in) :: bidon
integer(kind=8) :: val
real(kind=dp) :: val_flot
val_flot = transfer(this%lastrecord(mod(hash,this%nhist)+1),val_flot)
val_flot = val_flot + this%stride1(mod(hash,this%nhist)+1)
val = transfer(val_flot,val)
return
end function stride2_predict64
function stride2_predict32(this,hash,bidon) result(val)
class(TwoStridePredictorFPD) , intent(in) :: this
integer , intent(in) :: hash
real(kind=sp) , intent(in) :: bidon
integer(kind=8) :: val
real(kind=sp) :: val_flot
val_flot = transfer(this%lastrecord(mod(hash,this%nhist)+1),val_flot)
val_flot = val_flot + this%stride1(mod(hash,this%nhist)+1)
val = transfer(val_flot,val)
return
end function stride2_predict32
!! *********************************************************
subroutine datafile_update64(this,hash,val_flot,val_int)
class(DataFilePredictorFPD) , intent(inout) :: this
integer , intent(in) :: hash
real(kind=dp) , intent(in) :: val_flot
integer(kind=8) , intent(in) :: val_int
this%lastrecord(mod(hash,this%ncol)+1) = val_int
end subroutine datafile_update64
subroutine datafile_update32(this,hash,val_flot,val_int)
class(DataFilePredictorFPD) , intent(inout) :: this
integer , intent(in) :: hash
real(kind=sp) , intent(in) :: val_flot
integer(kind=8) , intent(in) :: val_int
this%lastrecord(mod(hash,this%ncol)+1) = val_int
end subroutine datafile_update32
!! *********************************************************
subroutine stride_update64(this,hash,val_flot,val_int)
class(StridePredictorFPD) , intent(inout) :: this
integer , intent(in) :: hash
real(kind=dp) , intent(in) :: val_flot
integer(kind=8) , intent(in) :: val_int
real(kind=dp) :: val_buf
val_buf = transfer(this%lastrecord(mod(hash,this%nhist)+1),val_buf)
this%stride(mod(hash,this%nhist)+1) = val_flot - val_buf
this%lastrecord(mod(hash,this%nhist)+1) = val_int
end subroutine stride_update64
subroutine stride_update32(this,hash,val_flot,val_int)
class(StridePredictorFPD) , intent(inout) :: this
integer , intent(in) :: hash
real(kind=sp) , intent(in) :: val_flot
integer(kind=8) , intent(in) :: val_int
real(kind=sp) :: val_buf
val_buf = transfer(this%lastrecord(mod(hash,this%nhist)+1),val_buf)
this%stride(mod(hash,this%nhist)+1) = val_flot - val_buf
this%lastrecord(mod(hash,this%nhist)+1) = val_int
end subroutine stride_update32
!! **********************************************************
subroutine stride2_update64(this,hash,val_flot,val_int)
class(TwoStridePredictorFPD) , intent(inout) :: this
integer , intent(in) :: hash
real(kind=dp) , intent(in) :: val_flot
integer(kind=8) , intent(in) :: val_int
real(kind=dp) :: val_buf
val_buf = transfer(this%lastrecord(mod(hash,this%nhist)+1),val_buf)
val_buf = val_flot - val_buf
! if (value - old predicted value == s2 )=> stride in s1
if ( val_buf == this%stride2(mod(hash,this%nhist)+1)) then
this%stride1(mod(hash,this%nhist)+1) = val_buf
end if
this%stride2(mod(hash,this%nhist)+1) = val_buf
this%lastrecord(mod(hash,this%nhist)+1) = val_int
end subroutine stride2_update64
subroutine stride2_update32(this,hash,val_flot,val_int)
class(TwoStridePredictorFPD) , intent(inout) :: this
integer , intent(in) :: hash
real(kind=sp) , intent(in) :: val_flot
integer(kind=8) , intent(in) :: val_int
real(kind=sp) :: val_buf
val_buf = transfer(this%lastrecord(mod(hash,this%nhist)+1),val_buf)
val_buf = val_flot - val_buf
! if (value - old predicted value == s2 )=> stride in s1
if ( val_buf == this%stride2(mod(hash,this%nhist)+1)) then
this%stride1(mod(hash,this%nhist)+1) = val_buf
end if
this%stride2(mod(hash,this%nhist)+1) = val_buf
this%lastrecord(mod(hash,this%nhist)+1) = val_int
end subroutine stride2_update32
!! *********************************************************
subroutine fcm_update64(this,hash,val_flot,val_int)
class(FCMPredictorFPD) , intent(inout) :: this
integer , intent(in) :: hash
real(kind=dp) , intent(in) :: val_flot
integer(kind=8) , intent(in) :: val_int
integer :: ihist,i,j
logical :: equal
real(kind=dp) :: val_buf
ihist = 1 ! mod(hash,this%nhist+1)
!seek in the context the corresponding history to set the value
do i=1,this%k
equal=.true.
do j=1,this%order
if ( this%history(j,ihist) /= this%context(i,j,ihist)) then
equal = .false.
exit
end if
end do
if (equal) then ! we find the corresponding history
!try to popup the value if val_int == this%valcontext(i,ihist)
this%valcontext(i,ihist) = val_int
exit
end if
end do
!none context was found. we add a new context
if ( .not. equal ) then
this%counter_context = mod(this%counter_context,this%k)+1
do j=1,this%order
this%context(this%counter_context,j,ihist) = this%history(j,ihist)
end do
this%valcontext(this%counter_context,ihist) = val_int
end if
!update the history
this%history(1:this%order-1,ihist)=this%history(2:this%order,ihist)
this%history(this%order,ihist) = val_int
end subroutine fcm_update64
subroutine fcm_update32(this,hash,val_flot,val_int)
class(FCMPredictorFPD) , intent(inout) :: this
integer , intent(in) :: hash
real(kind=sp) , intent(in) :: val_flot
integer(kind=8) , intent(in) :: val_int
integer :: ihist,i,j
logical :: equal
real(kind=sp) :: val_buf
ihist = 1 ! mod(hash,this%nhist+1)
!seek in the context the corresponding history to set the value
do i=1,this%k
equal=.true.
do j=1,this%order
if ( this%history(j,ihist) /= this%context(i,j,ihist)) then
equal = .false.
exit
end if
end do
if (equal) then ! we find the corresponding history
!try to popup the value if val_int == this%valcontext(i,ihist)
this%valcontext(i,ihist) = val_int
exit
end if
end do
!none context was found. we add a new context
if ( .not. equal ) then
this%counter_context = mod(this%counter_context,this%k)+1
do j=1,this%order
this%context(this%counter_context,j,ihist) = this%history(j,ihist)
end do
this%valcontext(this%counter_context,ihist) = val_int
end if
!update the history
this%history(1:this%order-1,ihist)=this%history(2:this%order,ihist)
this%history(this%order,ihist) = val_int
end subroutine fcm_update32
!! *********************************************************
subroutine datafile_init(this,nhist)
class(DataFilePredictorFPD) , intent(inout) :: this
integer , intent(in) :: nhist
integer :: io
character(len=256) :: error_mess
if ( nhist <= 0 ) then
write (0,*) "DataFilePredictorFPD : compress cannot ",&
"allocate array with a number of column <= 0 ",nhist
stop
end if
allocate (this%lastrecord(nhist),stat=io,errmsg=error_mess)
if ( io /= 0 ) then
write (0,*) "DataFilePredictorFPD compress_fpd:allocation error :",error_mess
stop
end if
this%lastrecord=0.
this%ncol = nhist
end subroutine datafile_init
!! *********************************************************
subroutine stride_init(this,nhist)
class(StridePredictorFPD) , intent(inout) :: this
integer , intent(in) :: nhist
integer :: io
character(len=256) :: error_mess
if (nhist <= 0) then
write (0,*) "StridePredictorFPD compress_fpd:Can not set nhist to 0"
stop
end if
allocate (this%lastrecord(nhist),stat=io,errmsg=error_mess)
if ( io /= 0 ) then
write (0,*) "StridePredictorFPD compress_fpd:allocation error :",error_mess
stop
end if
this%lastrecord=0.
allocate (this%stride(nhist),stat=io,errmsg=error_mess)
if ( io /= 0 ) then
write (0,*) "StridePredictorFPD : compress_fpd:allocation error :",error_mess
stop
end if
this%stride=0.
this%nhist=nhist
end subroutine stride_init
!! *********************************************************
subroutine stride2_init(this,nhist)
class(TwoStridePredictorFPD) , intent(inout) :: this
integer , intent(in) :: nhist
integer :: io
character(len=256) :: error_mess
if (nhist <= 0) then
write (0,*) "TwoStridePredictorFPD compress_fpd:Can not set nhist to 0"
stop
end if
allocate (this%lastrecord(nhist),stat=io,errmsg=error_mess)
if ( io /= 0 ) then
write (0,*) "TwoStridePredictorFPD compress_fpd:allocation error :",error_mess
stop
end if
this%lastrecord=0.
allocate (this%stride1(nhist),stat=io,errmsg=error_mess)
if ( io /= 0 ) then
write (0,*) "TwoStridePredictorFPD : compress_fpd:allocation error :",error_mess
stop
end if
allocate (this%stride2(nhist),stat=io,errmsg=error_mess)
if ( io /= 0 ) then
write (0,*) "TwoStridePredictorFPD : compress_fpd:allocation error :",error_mess
stop
end if
this%stride1=0.
this%stride2=0.
this%nhist=nhist
end subroutine stride2_init
!! *********************************************************
subroutine fcm_init(this,nhist)
class(FCMPredictorFPD) , intent(inout) :: this
integer , intent(in) :: nhist
integer :: io
character(len=256) :: error_mess
if (nhist <= 0) then
write (0,*) "FCMPredictorFPD compress_fpd:Can not set nhist to 0"
stop
end if
!this%nhist = nhist
allocate (this%history(this%order,1),stat=io,errmsg=error_mess)
if ( io /= 0 ) then
write (0,*) "TwoStridePredictorFPD : compress_fpd:allocation error :",error_mess
stop
end if
allocate (this%context(this%k,this%order,1),stat=io,errmsg=error_mess)
if ( io /= 0 ) then
write (0,*) "TwoStridePredictorFPD : compress_fpd:allocation error :",error_mess
stop
end if
allocate (this%valcontext(this%k,1),stat=io,errmsg=error_mess)
if ( io /= 0 ) then
write (0,*) "TwoStridePredictorFPD : compress_fpd:allocation error :",error_mess
stop
end if
! allocate (this%stride(this%k,this%nhist),stat=io,errmsg=error_mess)
if ( io /= 0 ) then
write (0,*) "TwoStridePredictorFPD : compress_fpd:allocation error :",error_mess
stop
end if
this%history = 0
this%context=-1
this%valcontext=0
this%counter_context=1
! this%stride=0
end subroutine fcm_init
!! *********************************************************
subroutine fcm_release(this)
class(FCMPredictorFPD) , intent(inout) :: this
if ( allocated(this%history) ) then
deallocate (this%history)
deallocate (this%context)
deallocate (this%valcontext)
! deallocate (this%stride)
end if
end subroutine fcm_release
!! *********************************************************
subroutine fcm_reset(this)
class(FCMPredictorFPD) , intent(inout) :: this
this%history = 0
this%context=0
this%valcontext=0
this%counter_context=1
! this%stride=0
end subroutine fcm_reset
!! *********************************************************
subroutine datafile_release(this)
class(DataFilePredictorFPD) , intent(inout) :: this
if ( allocated(this%lastrecord) ) then
deallocate (this%lastrecord)
end if
end subroutine datafile_release
!! *********************************************************
subroutine stride_release(this)
class(StridePredictorFPD) , intent(inout) :: this
if ( allocated(this%lastrecord) ) then
deallocate (this%lastrecord)
end if
if ( allocated(this%stride) ) then
deallocate (this%stride)
end if
end subroutine stride_release
!! *********************************************************
subroutine stride2_release(this)
class(TwoStridePredictorFPD) , intent(inout) :: this
if ( allocated(this%lastrecord) ) then
deallocate (this%lastrecord)
end if
if ( allocated(this%stride1) ) then
deallocate (this%stride1)
end if
if ( allocated(this%stride2) ) then
deallocate (this%stride2)
end if
end subroutine stride2_release
!! *********************************************************
subroutine datafile_reset(this)
class(DataFilePredictorFPD) , intent(inout) :: this
this%lastrecord = 0
end subroutine datafile_reset
!! *********************************************************
subroutine stride_reset(this)
class(StridePredictorFPD) , intent(inout) :: this
this%lastrecord = 0
this%stride = 0
end subroutine stride_reset
!! *********************************************************
subroutine stride2_reset(this)
class(TwoStridePredictorFPD) , intent(inout) :: this
this%lastrecord = 0
this%stride1 = 0
this%stride2 = 0
end subroutine stride2_reset
!! *********************************************************
function ratio(struct) result(val)
class(CompressFPD64) , intent(in) :: struct
real :: val
if ( struct%idxstream > 0 ) then
val = real(struct%nflottantTreated)/real(struct%idxstream)
else
val = 1.
end if
end function ratio
!! *********************************************************
subroutine info_CompressFPD64(this,unit)
class(CompressFPD64) , intent(in) :: this
integer , intent(in) :: unit
write (unit,*) '===================== INFO STREAM =================== '
write (unit,*) ' memory usage =',this%nstream
write (unit,*) ' current index =',this%idxstream
write (unit,*) ' binary index =',this%idxbitstream
write (unit,*) ' FPD coded =',this%nflottantTreated
write (unit,*) ' stream allocated =',associated(this%stream)
write (unit,*) ' size stream =',size(this%stream)
end subroutine info_CompressFPD64
!! *********************************************************
subroutine resize_stream(this)
class(CompressFPD64) , intent(inout) :: this
integer(kind=8) ,dimension(:),allocatable :: stream_buf
integer :: io
character(len=256) :: error_mess
allocate (stream_buf(this%nstream),stat=io,errmsg=error_mess)
if ( io /= 0 ) then
write (0,*) "CompressFPD64 : compress_fpd:allocation error :",error_mess, 'alloc_size:',this%nstream
stop
end if
stream_buf(:this%nstream) = this%stream(:this%nstream)
deallocate (this%stream)
allocate (this%stream(this%nstream+this%BLOCK_SIZE_ALLOC),stat=io,errmsg=error_mess)
if ( io /= 0 ) then
write (0,*) "CompressFPD64 : compress_fpd:allocation error :",error_mess, 'alloc_size:',&
this%nstream+this%BLOCK_SIZE_ALLOC
stop
end if
! print *,this%nstream,size(stream_buf),size(this%stream)
this%stream(:this%nstream) = stream_buf
this%stream(this%nstream+1:)=0
this%nstream = this%nstream+this%BLOCK_SIZE_ALLOC
deallocate (stream_buf)
write (*,*) "resize stream =",(real(this%nstream)*4.)/1024.," Ko"
end subroutine resize_stream
!! *********************************************************
! Add ZCL et DIFF information in a binary stream
subroutine encode_stream64(this,NBITS_ZCL,NBITS,nb,ZCL,DIFF)
class(CompressFPD64) , intent(inout) :: this
integer , intent(in) :: NBITS_ZCL
integer , intent(in) :: NBITS
integer , intent(in) :: nb
integer(kind=8) , dimension(nb) , intent(in) :: ZCL
integer(kind=8) , dimension(nb) , intent(in) :: DIFF
integer :: icol,sizerec
integer(kind=8) :: code
#ifdef DEBUG_MOD
print *," ===================================================================="
print *," ===*** encode_stream64 ***==="
print *," ===*** ZCL =",ZCL
print *," ===*** DIFF =",DIFF
print *," ===================================================================="
#endif
!on stoque les valeurs de droite à gauche dans chaque entier (et non de gauche à droite),
! ca evite des calculs supplementaires
do icol=1,nb
#ifdef DEBUG_MOD
print *,"*********** VAL ",icol," ************************"
#endif
! NBITS_ZCL_SP bits pour code ZCL
code = this%getCode(ZCL(icol),NBITS,NBITS_ZCL)
call this%addstream(NBITS_ZCL,code)
! 32 - ZLC bits pour coder DIFF
sizerec=NBITS-this%getZCL(code,NBITS,NBITS_ZCL) ! different from first zcl
call this%addstream(sizerec,DIFF(icol))
this%nflottantTreated=this%nflottantTreated+1
end do
#ifdef DEBUG_MOD
print *,"FPD coded=",this%nflottantTreated," nb integer coded=",this%idxstream
#endif
end subroutine encode_stream64
!! *********************************************************
! Add ZCL et DIFF information in a binary stream
subroutine decode_stream64(this,NBITS_ZCL,NBITS,nb,ZCL,DIFF)
class(CompressFPD64) , intent(inout) :: this
integer , intent(in) :: NBITS_ZCL
integer , intent(in) :: NBITS
integer , intent(in) :: nb
integer(kind=8) , dimension(nb) , intent(inout) :: ZCL
integer(kind=8) , dimension(nb) , intent(inout) :: DIFF
integer :: val_buf,icol,sizerec,sizepart,startfrom
#ifdef DEBUG_MOD
print *," ===*** decode_stream ***==="
#endif
do icol=1,nb
#ifdef DEBUG_MOD
print *,"*********** VAL ",icol," ************************"
#endif
call this%getstream(NBITS_ZCL,ZCL(icol))
sizerec=NBITS-this%getZCL(ZCL(icol),NBITS,NBITS_ZCL)
call this%getstream(sizerec,DIFF(icol))
this%nflottantTreated=this%nflottantTreated+1
end do
#ifdef DEBUG_MOD
print *,"ZCL =",ZCL
print *,"DIFF =",DIFF
#endif
end subroutine decode_stream64
!! *********************************************************
subroutine addstream64(this,sizeval,val)
class(CompressFPD64) ,intent(inout) :: this
integer ,intent(in) :: sizeval
integer(kind=8) ,intent(in) :: val
integer(kind=8) :: val_buf
integer :: sizepart,v
integer ,parameter :: NBITS_INTEGER=bit_size(this%stream)
#ifdef DEBUG_MOD
print *,"ADD=",val, " SIZE=",sizeval
if ( sizeval > NBITS_INTEGER ) then
write (0,*) "encode_stream:sizerec [",sizeval,"] > INTEGER_PRECISION =",NBITS_INTEGER
stop
end if
#endif
if ( sizeval <= 0 ) return
val_buf = this%stream(this%idxstream)
! Le codage rentre dans l'entier courant du stream
if ( (this%idxbitstream + sizeval) <= NBITS_INTEGER ) then
call mvbits(val,0,sizeval,val_buf,this%idxbitstream)
this%idxbitstream = this%idxbitstream + sizeval
this%stream(this%idxstream) = val_buf
if ( this%idxbitstream >= NBITS_INTEGER ) then
this%idxbitstream = 0
this%idxstream = this%idxstream + 1
if ( this%idxstream > this%nstream ) then
call this%resize_stream()
end if
end if
else ! Il faut coder l'entrée de cette valeur à cheval entre deux entiers consecutifs de stream
sizepart = ( NBITS_INTEGER - this%idxbitstream )
call mvbits(val,0,sizepart,val_buf,this%idxbitstream)
!save
this%stream(this%idxstream) = val_buf
!load new integer
this%idxstream = this%idxstream + 1
if ( this%idxstream > this%nstream ) then
call this%resize_stream()
end if
val_buf = this%stream(this%idxstream)
! move remaining data
this%idxbitstream = sizeval-sizepart
call mvbits(val,sizepart,this%idxbitstream,val_buf,0)
this%stream(this%idxstream) = val_buf
end if
#ifdef DEBUG_MOD
print *,'insert VAL=',val_buf, " new index=",this%idxbitstream, &
" nflottantcoded=",this%nflottantTreated, " ninteger used=",this%idxstream
#endif
end subroutine addstream64
!! *********************************************************
subroutine getstream64(this,sizeval,val)
class(CompressFPD64) ,intent(inout) :: this
integer ,intent(in) :: sizeval
integer(kind=8) ,intent(inout) :: val
integer(kind=8) :: val_buf
integer :: sizepart,startfrom
integer ,parameter :: NBITS_INTEGER=bit_size(this%stream)
#ifdef DEBUG_MOD
print *,"EXTRACT SIZE",sizeval
if ( sizeval > NBITS_INTEGER ) then
write (0,*) "getstream64 size: [",sizeval,"] > INTEGER_PRECISION =",NBITS_INTEGER
stop
end if
#endif
val = 0
if ( sizeval <= 0 ) return
if ( this%idxstream > this%nstream ) then
call this%info(0)
write (0,*) " *** Error fpd_compress:getstream: reach end of stream ! *** "
stop
end if
val_buf = this%stream(this%idxstream)
if ( (this%idxbitstream + sizeval) <= NBITS_INTEGER ) then
call mvbits(val_buf,this%idxbitstream,sizeval,val,0)
this%idxbitstream = this%idxbitstream + sizeval
if ( this%idxbitstream >= NBITS_INTEGER ) then
this%idxbitstream = 0
this%idxstream = this%idxstream + 1
end if
else
sizepart = ( NBITS_INTEGER - this%idxbitstream )
call mvbits(val_buf,this%idxbitstream,sizepart,val,0)
!load new integer
this%idxstream = this%idxstream + 1
if ( this%idxstream > this%nstream ) then
call this%info(0)
write (0,*) " *** Error fpd_compress:getstream: reach end of stream ! *** "
stop
end if
val_buf = this%stream(this%idxstream)
! move remaining data
this%idxbitstream = sizeval-sizepart
call mvbits(val_buf,0,this%idxbitstream,val,sizepart)
end if
#ifdef DEBUG_MOD
print *,'extract VAL=',val, " new index=",this%idxbitstream, &
" nflottantcoded=",this%nflottantTreated, " ninteger used=",this%idxstream
#endif
end subroutine getstream64
!! *********************************************************
subroutine init64(this,nstream)
class(CompressFPD64) ,intent(inout) :: this
integer ,intent(in) :: nstream
integer :: io
character(len=256) :: error_mess
if ( .not. associated(this%stream) ) then
allocate (this%stream(nstream),stat=io,errmsg=error_mess)
else
if ( size(this%stream)< nstream ) then
deallocate (this%stream)
allocate (this%stream(nstream),stat=io,errmsg=error_mess)
else
this%stream=0
return
end if
end if
if ( io /= 0 ) then
write (0,*) "compress_fpd:init64:allocation error :",error_mess
this%nstream=0
else
this%stream=0
this%nstream=nstream
end if
end subroutine init64
!! *********************************************************
! nbvalues correspond aux nombres de flottants à compresser
subroutine set_CompressFPD64(this,predictsize)
class(CompressFPD64) , intent(inout) :: this
integer ,optional , intent(in) :: predictsize
if ( present(predictsize) ) then
this%nstream = predictsize
else
this%nstream = this%BLOCK_SIZE_ALLOC
end if
this%idxstream = 1
this%idxbitstream = 0
this%nflottantTreated=0
call this%init(this%nstream)
end subroutine set_CompressFPD64
subroutine set_UncompressFPD64(this,predictsize)
class(CompressFPD64) , intent(inout) :: this
integer ,optional , intent(in) :: predictsize
if ( present(predictsize) ) then
this%nstream = predictsize
else
this%nstream = this%BLOCK_SIZE_ALLOC
end if
this%idxstream = 1
this%idxbitstream = 0
this%nflottantTreated=0
call this%init(this%nstream)
end subroutine set_UncompressFPD64
!! *********************************************************
subroutine release_CompressFPD64(this)
class(CompressFPD64) , intent(inout) :: this
this%nstream = 0
this%idxstream = 0
this%idxbitstream = 0
this%nflottantTreated=0
deallocate (this%stream)
end subroutine release_CompressFPD64
!! *********************************************************
subroutine rewind(this,predictor)
class(CompressFPD64) , intent(inout) :: this
class(PredictorFPD) , intent(inout) :: predictor
this%idxstream = 1
this%idxbitstream = 0
call predictor%reset()
end subroutine rewind
!! *********************************************************
subroutine getStream(struct)
class(CompressFPD64) , intent(inout) :: struct
end subroutine getStream
!! *********************************************************
subroutine setStream(struct)
class(CompressFPD64) , intent(inout) :: struct
end subroutine setStream
!! **********************************************************
function getcode(compr,zcl,NBITS_FLOAT,NBITS_ZCL) result(code)
class(CompressFPD64) ,intent(in) :: compr
integer(kind=8) ,intent(in) :: zcl
integer ,intent(in) :: NBITS_FLOAT ! 32 ou 64
integer ,intent(in) :: NBITS_ZCL
integer(kind=8) :: code
integer :: step,i,cval
code = 2**NBITS_ZCL - 1
if ( code >= NBITS_FLOAT ) then
code = zcl
return
end if
! one code for zcl = 32 or 64
if ( NBITS_FLOAT == zcl ) return
!step for code
step = NBITS_FLOAT / code
cval = NBITS_FLOAT - 1
do code=code-1,1,-1
cval=cval - step
if ( zcl >= cval) return
end do
code=0
end function getcode
function getZCL(compr,code,NBITS_FLOAT,NBITS_ZCL) result(zcl)
class(CompressFPD64) ,intent(in) :: compr
integer(kind=8) ,intent(in) :: code
integer ,intent(in) :: NBITS_FLOAT ! 32 ou 64
integer ,intent(in) :: NBITS_ZCL
integer(kind=8) :: zcl
integer :: step,transcode,i,cval
transcode = 2**NBITS_ZCL - 1
if ( transcode >= NBITS_FLOAT ) then
zcl = code
return
end if
zcl = NBITS_FLOAT
if ( transcode == code ) return
!step for code
step = NBITS_FLOAT / (transcode)
zcl = zcl - 1
do transcode = transcode-1,1,-1
zcl = zcl - step
if ( transcode == code ) return
end do
zcl = 0
end function getZCL
!! *********************************************************
subroutine compress64(compr,predictor,nb,values)
class(CompressFPD64) ,intent(inout) :: compr
class(PredictorFPD) ,intent(inout) :: predictor
integer ,intent(in) :: nb
real(kind=dp) , dimension(nb) , intent(in) :: values
integer(kind=8) , dimension(nb) :: ZCL
integer(kind=8) , dimension(nb) :: DIFF
integer(kind=8) :: compareval,predictvalue
integer :: icol,i,ZCL_b
integer , parameter :: bitsize= bit_size(DIFF)
if ( compr%idxstream == 0 ) then
write (0,*) "==============================================="
write (0,*) " ** stream is not init ! Call set subroutine **"
write (0,*) "==============================================="
stop
end if
! for each column, we encode the value : ZCL and DIFF
do icol = 1,nb
compareval = transfer(values(icol),compareval)
predictvalue = predictor%predict64(icol,values(1))
DIFF(icol) = IEOR(predictvalue,compareval)
ZCL_b=0
do i=bitsize-1,0,-1
if ( btest(DIFF(icol),i) ) exit
ZCL_b=ZCL_b+1
end do
ZCL(icol)=ZCL_b
call predictor%update64(icol,values(icol),compareval)
end do
call compr%encode_stream64(NBITS_ZLC_SELECT,NBITS_DP,nb,ZCL,DIFF)
end subroutine compress64
!! *********************************************************
subroutine compress32(compr,predictor,nb,values)
class(CompressFPD64) ,intent(inout) :: compr
class(PredictorFPD) ,intent(inout) :: predictor
integer ,intent(in) :: nb
real(kind=sp) , dimension(nb) , intent(in) :: values
integer(kind=8) :: compareval,predictvalue
integer(kind=4) :: comp32
integer :: icol,i,ZCL_b
integer(kind=8) , dimension(nb) :: ZCL
integer(kind=8) , dimension(nb) :: DIFF
integer , parameter :: bitsize= bit_size(DIFF)
! real(kind=dp) , dimension(nb) :: values_DP
! values_dp = values
! call compress64(compr,predictor,nb,values_dp)
! values_DP = values
if ( compr%idxstream == 0 ) then
write (0,*) "==============================================="
write (0,*) " ** stream is not init ! Call set subroutine **"
write (0,*) "==============================================="
stop
end if
! for each column, we encode the value : ZCL and DIFF
do icol = 1,nb
!! correction bug ofi => in 32 transfert(0_32,0) /= 0 with gcc 4.8.* ....
!!compareval = transfer(values(icol),compareval)
comp32 = transfer(values(icol),comp32)
compareval = comp32
!print *,"add val=",values(icol)," => ",compareval
predictvalue = predictor%predict32(icol,values(1))
DIFF(icol) = IEOR(predictvalue,compareval)
ZCL_b=0
do i=bitsize-1,0,-1
if ( btest(DIFF(icol),i) ) exit
ZCL_b=ZCL_b+1
end do
if ( ZCL_b < NBITS_SP ) then
print *,"STOP ERROR ZCL_b=",ZCL_b," *Simple precision Context*",NBITS_SP
stop
end if
ZCL(icol)=ZCL_b - NBITS_SP
! print *,"===>",ZCL(icol),compr%getcode(ZCL(icol),NBITS_SP,3),compr%getZCL(compr%getcode(ZCL(icol),NBITS_SP,3),NBITS_SP,3)
call predictor%update32(icol,values(icol),compareval)
end do
call compr%encode_stream64(NBITS_ZLC_SELECT,NBITS_SP,nb,ZCL,DIFF)
end subroutine compress32
!! *********************************************************
subroutine uncompress64(compr,predictor,nb,values)
class(CompressFPD64) , intent(inout) :: compr
class(PredictorFPD) , intent(inout) :: predictor
real(kind=dp) , dimension(nb) , intent(inout) :: values
integer ,intent(in) :: nb
integer(kind=8) , dimension(nb) :: ZCL
integer(kind=8) , dimension(nb) :: DIFF
integer(kind=8) :: compareval,predictvalue
integer :: icol,i,ZCL_b
if ( compr%idxstream == 0 ) then
write (0,*) "stream is not init !"
return
end if
call compr%decode_stream64(NBITS_ZLC_SELECT,NBITS_DP,nb,ZCL,DIFF)
! for each column, we decode the value : ZCL and DIFF
do icol = 1, nb
predictvalue = predictor%predict64(icol,values(1))
compareval = IEOR(predictvalue,DIFF(icol))
values(icol) = transfer(compareval,values(icol))
call predictor%update64(icol,values(icol),compareval)
end do
end subroutine uncompress64
!! *********************************************************
subroutine uncompress32(compr,predictor,nb,values)
class(CompressFPD64) , intent(inout) :: compr
class(PredictorFPD) ,intent(inout) :: predictor
real(kind=sp) , dimension(nb) , intent(inout) :: values
integer ,intent(in) :: nb
integer(kind=8) , dimension(nb) :: ZCL
integer(kind=8) , dimension(nb) :: DIFF
integer(kind=8) :: compareval,predictvalue
integer :: icol,i,ZCL_b
if ( compr%idxstream == 0 ) then
write (0,*) "stream is not init !"
return
end if
call compr%decode_stream64(NBITS_ZLC_SELECT,NBITS_SP,nb,ZCL,DIFF)
! for each column, we decode the value : ZCL and DIFF
do icol = 1, nb
! print *,"<===",ZCL(icol),DIFF(icol)
predictvalue = predictor%predict32(icol,values(1))
compareval = IEOR(predictvalue,DIFF(icol))
values(icol) = transfer(compareval,values(icol))
call predictor%update32(icol,values(icol),compareval)
end do
end subroutine uncompress32
!!! ********************* ========== TEST SUBROUTINE ============= *************************************
subroutine test_module_FPD
type(StridePredictorFPD) :: pred1
type(DataFilePredictorFPD) :: pred2
type(TwoStridePredictorFPD) :: pred3
type(FCMPredictorFPD) :: pred_fcm
integer , dimension(100) :: suite
! call test_file(pred_fcm)
! stop
print *," ******************************** "
print *," *** Test ajout ZERO *** "
print *," ******************************** "
call testzero
print *," ******************************** "
print *," *** Add 1 elt in Stream < 64 *** "
print *," ******************************** "
call test_add_get(10)
print *," *********************************** "
print *," *** Add 1000 elt in Stream *** "
print *," *********************************** "
call test_add_get_loop(10,1000)
!print *," *********************************** "
!print *," *** compres32/uncompres32 *** "
!print *," *********************************** "
!call test_random_simple32
print *," *********************************** "
print *," *** compres64/uncompres64 *** "
print *," *********************************** "
call test_random_simple64
print *," *********************************************************** "
print *," *** Test Encodage SUITE SIMPLE - Bench Double precision *** "
print *," *********************************************************** "
print *," *** ============== StridePredictorFPD ============= *** "
call test_suite_simple(pred1,1,1000)
print *," *** ============== DataFilePredictorFPD ============= *** "
call test_suite_simple(pred2,1,1000)
print *," *** ============== TwoStridePredictorFPD ============= *** "
call test_suite_simple(pred3,1,1000)
print *," *** ============== FCMPredictorFPD ============= *** "
call test_suite_simple(pred_fcm,1,1000)
!print *," ****************************** "
!print *," *** Bench Simple precision *** "
!print *," ****************************** "
!print *,"========================================================="
!print *," ======== SUITE 1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4 ======= "
!suite(1:16)=(/1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4/)
!print *," *** ============== DataFilePredictorFPD ============= *** "
!call test_suite32(pred2,1,16,suite);print *;print *
!print *," *** ============== StridePredictorFPD ============= *** "
!call test_suite32(pred1,1,16,suite);print *;print *
!print *," *** ============== TwoStridePredictorFPD ============= *** "
!call test_suite32(pred3,1,16,suite);print *;print *
!print *," *** ============== FCMPredictorFPD ============= *** "
!call test_suite32(pred_fcm,1,16,suite);print *;print *
!print *,"========================================================="
!print *," ======== SUITE 3,4,1,9,3,4,1,9,3,4,1,9,3,4,1,9 ======= "
!suite(1:16)=(/3,4,1,9,3,4,1,9,3,4,1,9,3,4,1,9/)
!print *," *** ============== DataFilePredictorFPD ============= *** "
!call test_suite32(pred2,1,16,suite);print *;print *
!print *," *** ============== StridePredictorFPD ============= *** "
!call test_suite32(pred1,1,16,suite);print *;print *
!print *," *** ============== TwoStridePredictorFPD ============= *** "
!call test_suite32(pred3,1,16,suite);print *;print *
!print *," *** ============== FCMPredictorFPD ============= *** "
!call test_suite32(pred_fcm,1,16,suite);print *;print *
!print *," ======== RANDOM ======= "
!print *," *** ============== DataFilePredictorFPD/32 ============= *** "
!call test_random32(pred2,1,100000)
!print *," *** ============== StridePredictorFPD/32 ============= *** "
!call test_random32(pred1,1,100000)
!print *," *** ============== TwoStridePredictorFPD/32 ============= *** "
!call test_random32(pred3,1,100000)
!print *," *** ============== FCMPredictorFPD/32 ============= *** "
!call test_random32(pred_fcm,1,100000)
print *," ****************************** "
print *," *** Bench Double precision *** "
print *," ****************************** "
print *," *** ============== StridePredictorFPD/64 ============= *** "
call test_random64(pred1,1,100000)
print *," *** ============== DataFilePredictorFPD/64 ============= *** "
call test_random64(pred2,1,100000)
print *," *** ============== TwoStridePredictorFPD/64 ============= *** "
call test_random64(pred3,1,100000)
print *," *** ============== FCMPredictorFPD/64 ============= *** "
call test_random64(pred_fcm,1,100000)
stop
end subroutine test_module_FPD
subroutine testzero
type(CompressFPD64) :: compr
integer(kind=8) :: val_curr
real(kind=sp), dimension(5) :: r,values = (/ 0.,1.,16.,400.7208,0./)
type(DataFilePredictorFPD) :: pred_data
call pred_data%init(5)
call compr%setcompress(5)
call compr%compress32(pred_data,5,values)
call compr%rewind(pred_data)
call compr%uncompress32(pred_data,5,r)
if ( count(r == values) /= 5 ) then
call compr%info(6)
write (0,*) "false : expected ",values," val=",r
stop
end if
call compr%release()
call pred_data%release()
call compr%setcompress(100)
call compr%addstream(23,111_8)
call compr%addstream(23,111_8)
call compr%addstream(23,111_8)
call compr%addstream(23,111_8)
call compr%addstream(23,111_8)
call compr%addstream(23,111_8)
call compr%addstream(6,32_8)
call compr%addstream(0,0_8)
compr%idxstream=1
compr%idxbitstream=0
call compr%getstream(23,val_curr)
call compr%getstream(23,val_curr)
call compr%getstream(23,val_curr)
call compr%getstream(23,val_curr)
call compr%getstream(23,val_curr)
call compr%getstream(23,val_curr)
call compr%getstream(6,val_curr)
if ( val_curr /= 32 ) then
write (0,*) "Error Test ==> 32 expected value val=",val_curr
stop
end if
call compr%getstream(0,val_curr)
if ( val_curr /= 0 ) then
write (0,*) "Error Test ==> 0 expected value val=",val_curr
stop
end if
write (*,*) "[OK] add 0, size=9"
end subroutine testzero
subroutine test_add_get(ncol)
integer , intent(in) :: ncol
type(CompressFPD64) :: compr
integer :: i
integer(kind=8) :: val_curr
!! =========================================
call compr%setcompress(1)
call compr%addstream(9,2_8)
compr%idxstream=1
compr%idxbitstream=0
call compr%getstream(9,val_curr)
if ( val_curr /= 2 ) then
write (0,*) "Error Test ==> 2 expected value val=",val_curr
stop
end if
write (*,*) "[OK] add 2, size=9"
!! =========================================
call compr%setcompress(1)
call compr%addstream(64,2_8)
compr%idxstream=1
compr%idxbitstream=0
call compr%getstream(64,val_curr)
if ( val_curr /= 2 ) then
write (0,*) "Error Test ==> 2 expected value val=",val_curr
stop
end if
end subroutine test_add_get
subroutine test_add_get_loop(ncol,nloop)
integer , intent(in) :: ncol
integer , intent(in) :: nloop
type(CompressFPD64) :: compr
integer :: i
integer(kind=8) :: val_curr
call compr%setcompress(nloop)
do i=1,nloop
call compr%addstream(9,2_8)
end do
compr%idxstream=1
compr%idxbitstream=0
do i=1,nloop
call compr%getstream(9,val_curr)
if ( val_curr /= 2 ) then
write (0,*) "Error Test ==> 2 expected value val=",val_curr
stop
end if
end do
end subroutine test_add_get_loop
subroutine test_random_simple32
type(CompressFPD64) :: compr
integer :: i
real :: valtab(1),r(1)
type(DataFilePredictorFPD) :: pred_data
call pred_data%init(1)
call random_number(valtab)
call compr%setcompress(1)
call compress32(compr,pred_data,1,valtab)
call compr%rewind(pred_data)
call uncompress32(compr,pred_data,1,r)
if ( r(1) /= valtab(1) ) then
call compr%info(6)
write (0,*) "false : expected ",valtab(1)," val=",r(1)
stop
end if
call compr%release()
call pred_data%release()
end subroutine test_random_simple32
subroutine test_random_simple64
type(CompressFPD64) :: compr
integer :: i
real(kind=dp) :: valtab(1),r(1)
type(DataFilePredictorFPD) :: pred_data
call pred_data%init(1)
call random_number(valtab)
call compr%setcompress(1)
call compress64(compr,pred_data,1,valtab)
call compr%rewind(pred_data)
call uncompress64(compr,pred_data,1,r)
if ( r(1) /= valtab(1) ) then
call compr%info(6)
write (0,*) "false : expected ",valtab(1)," val=",r(1)
stop
end if
call compr%release()
call pred_data%release()
end subroutine test_random_simple64
subroutine test_random32(pred,nhist,nloop)
class(PredictorFPD) , intent(inout) :: pred
integer , intent(in) :: nhist
integer , intent(in) :: nloop
type(CompressFPD64) :: compr
integer :: i,ii
real :: r(1)
real , dimension(:), allocatable :: valtab
real :: start, finish
call cpu_time(start)
call pred%init(nhist)
allocate (valtab(nloop))
call random_number(valtab)
valtab=valtab*1000
call compr%setcompress(nloop)
do i=1,nloop
call compress32(compr,pred,1,valtab(i))
end do
call cpu_time(finish)
print '("Time Compress= ",f6.3," seconds."," NFLOT = ",I7)',finish-start
print *," ====> RATIO =",compr%ratio()
start=finish
call compr%rewind(pred)
do i=1,nloop
call uncompress32(compr,pred,1,r)
if ( r(1) /= valtab(i) ) then
call compr%info(6)
write (0,*) "false : expected ",valtab(i)," val=",r(1), " iloop=",i
stop
end if
end do
deallocate (valtab)
write (*,*) "[Ok]"
call cpu_time(finish)
print '("Time Decompr= ",f6.3," seconds."," NFLOT = ",I7)',finish-start,nloop
call compr%release()
call pred%release()
end subroutine test_random32
subroutine test_suite32(pred,nhist,sizes,suite)
class(PredictorFPD) , intent(inout) :: pred
integer , intent(in) :: nhist
integer , intent(in) :: sizes
integer ,dimension(:) , intent(in) :: suite
type(CompressFPD64) :: compr
integer :: i,ii
real(kind=dp) , dimension(nhist) :: valtab
real :: start, finish
call cpu_time(start)
call pred%release()
call pred%init(nhist)
call compr%setcompress(sizes)
do i=1,sizes,nhist
do ii=1,nhist
valtab(ii)=suite(i+ii-1)
end do
call compress64(compr,pred,nhist,valtab)
end do
call cpu_time(finish)
print '("Time Compress= ",f6.3," seconds."," NFLOT = ",I7)',finish-start
print *,"======================================================"
print *," ============== RATIO =",compr%ratio()," ============"
print *,"======================================================"
print *,"-------------------------"
call compr%info(6)
print *,"-------------------------"
start=finish
call compr%rewind(pred)
do i=1,sizes,nhist
call uncompress64(compr,pred,nhist,valtab)
do ii=1,nhist
if ( suite(i+ii-1) /= valtab(ii) ) then
call compr%info(6)
write (0,*) "false : val=",valtab(i)," expected ",suite(i+ii-1), " iloop=",i
stop
end if
end do
end do
write (*,*) "[Ok]"
call cpu_time(finish)
print '("Time Decompr= ",f6.3," seconds."," NFLOT = ",I7)',finish-start,sizes
call compr%release()
call pred%release()
end subroutine test_suite32
subroutine test_suite_simple(pred,nhist,nloop)
class(PredictorFPD) , intent(inout) :: pred
integer , intent(in) :: nhist
integer , intent(in) :: nloop
type(CompressFPD64) :: compr
integer :: i,ii
real(kind=dp) , dimension(:), allocatable :: valtab
real :: start, finish
call cpu_time(start)
call pred%init(nhist)
allocate (valtab(nhist))
call compr%setcompress(nloop)
do i=1,nloop,nhist
do ii=1,nhist
valtab(ii)=i+ii-1
end do
call compress64(compr,pred,nhist,valtab)
end do
call cpu_time(finish)
print '("Time Compress= ",f6.3," seconds."," NFLOT = ",I7)',finish-start
print *," ========================== "
print *," ====RATIO =",compr%ratio()
print *," ========================== "
! print *,"-------------------------"
! call compr%info(6)
! print *,"-------------------------"
start=finish
call compr%rewind(pred)
do i=1,nloop,nhist
call uncompress64(compr,pred,nhist,valtab)
do ii=1,nhist
if ( (i + ii -1) /= valtab(ii) ) then
call compr%info(6)
write (0,*) "false : val=",valtab(i)," expected ",(i + ii -1), " iloop=",i
stop
end if
end do
end do
deallocate (valtab)
write (*,*) "[Ok]"
call cpu_time(finish)
print '("Time Decompr= ",f6.3," seconds."," NFLOT = ",I7)',finish-start,nloop
call compr%release()
call pred%release()
end subroutine test_suite_simple
subroutine test_random64(pred,nhist,nloop)
class(PredictorFPD) , intent(inout) :: pred
integer , intent(in) :: nhist
integer , intent(in) :: nloop
type(CompressFPD64) :: compr
integer :: i,ii
real(kind=dp) :: r(1)
real(kind=dp) , dimension(:), allocatable :: valtab
real :: start, finish
call cpu_time(start)
call pred%init(nhist)
allocate (valtab(nloop))
call random_number(valtab)
valtab=valtab*1000
call compr%setcompress(nloop)
do i=1,nloop
call compress64(compr,pred,1,valtab(i))
end do
call cpu_time(finish)
print '("Time Compress= ",f6.3," seconds."," NFLOT = ",I7)',finish-start
print *," ====> RATIO =",compr%ratio()
start=finish
call compr%rewind(pred)
do i=1,nloop
call uncompress64(compr,pred,1,r)
if ( r(1) /= valtab(i) ) then
call compr%info(6)
write (0,*) "false : expected ",valtab(i)," val=",r(1), " iloop=",i
stop
end if
end do
deallocate (valtab)
write (*,*) "[Ok]"
call cpu_time(finish)
print '("Time Decompr= ",f6.3," seconds."," NFLOT = ",I7)',finish-start,nloop
call compr%release()
call pred%release()
end subroutine test_random64
!! *************************************************************************************
subroutine test_file(pred)
class(PredictorFPD) , intent(inout) :: pred
type(CompressFPD64) :: compr
integer :: i,ii
real(kind=dp) , dimension(14) :: valtab
real :: start, finish
real(kind=dp) , dimension(:,:) ,allocatable :: datafile
allocate (datafile(100,14))
datafile = transpose(reshape((/&
1.,1.,61.,40.,30.,1.,32.,2.,1.,1.,0.,1.,16.,400.7208068, &
1.,2.,61.,40.,30.,1.,64.,2.,1.,1.,0.,1.,16.,378.6092405, &
1.,3.,61.,40.,30.,1.,102.,2.,1.,1.,20.,1.,16.,422.8063455, &
1.,4.,61.,40.,30.,1.,134.,2.,1.,1.,52.,1.,16.,446.1524943, &
1.,5.,61.,40.,30.,1.,163.,2.,1.,1.,81.,1.,16.,404.3591163, &
1.,6.,61.,40.,30.,1.,191.,2.,1.,1.,109.,1.,16.,482.8101775, &
1.,7.,61.,40.,30.,1.,222.,2.,1.,1.,140.,1.,16.,461.8192922, &
1.,8.,61.,40.,30.,1.,253.,2.,1.,1.,171.,1.,16.,493.2272792, &
1.,9.,61.,40.,30.,1.,282.,2.,1.,1.,200.,1.,16.,452.6028508, &
1.,10.,72.,48.,36.,2.,347.,6.,2.,1.,0.,2.,17.,356.8576225, &
1.,11.,72.,48.,36.,2.,375.,6.,2.,1.,0.,2.,17.,386.8811236, &
1.,12.,72.,48.,36.,2.,412.,6.,2.,1.,8.,2.,17.,375.7816156, &
1.,13.,72.,48.,36.,2.,440.,6.,2.,1.,36.,2.,17.,387.1260413, &
1.,14.,72.,48.,36.,2.,468.,6.,2.,1.,64.,2.,17.,415.1781001, &
1.,15.,72.,48.,36.,2.,497.,6.,2.,1.,93.,2.,17.,435.0262218, &
1.,16.,72.,48.,36.,2.,529.,6.,2.,1.,125.,2.,17.,395.7932483, &
1.,17.,72.,48.,36.,2.,558.,6.,2.,1.,154.,2.,17.,452.8856378, &
1.,18.,72.,48.,36.,2.,588.,6.,2.,1.,184.,2.,17.,457.3265912, &
1.,19.,81.,54.,43.,3.,647.,11.,5.,1.,0.,3.,18.,437.0774596, &
1.,20.,81.,54.,43.,3.,676.,11.,5.,1.,0.,3.,18.,382.5792859, &
1.,21.,81.,54.,43.,3.,713.,11.,5.,1.,0.,3.,18.,382.8253039, &
1.,22.,81.,54.,43.,3.,745.,11.,5.,1.,0.,3.,18.,410.4807373, &
1.,23.,81.,54.,43.,3.,773.,11.,5.,1.,4.,3.,18.,454.1973743, &
1.,24.,81.,54.,43.,3.,803.,11.,5.,1.,34.,3.,18.,421.1965999, &
1.,25.,81.,54.,43.,3.,835.,11.,5.,1.,66.,3.,18.,421.1075783, &
1.,26.,81.,54.,43.,3.,864.,11.,5.,1.,95.,3.,18.,416.0383661, &
1.,27.,81.,54.,43.,3.,892.,11.,5.,1.,124.,3.,18.,412.0377769, &
2.,2.,62.,40.,30.,1.,31.,3.,1.,2.,0.,1.,16.,470.7428877, &
2.,3.,62.,40.,30.,1.,69.,3.,1.,2.,3.,1.,16.,493.6315058, &
2.,4.,62.,40.,30.,1.,101.,3.,1.,2.,35.,1.,16.,530.4416604, &
2.,5.,62.,40.,30.,1.,130.,3.,1.,2.,64.,1.,16.,476.2564778, &
2.,6.,62.,40.,30.,1.,158.,3.,1.,2.,92.,1.,16.,477.3487260, &
2.,7.,62.,40.,30.,1.,189.,3.,1.,2.,123.,1.,16.,499.4842557, &
2.,8.,62.,40.,30.,1.,220.,3.,1.,2.,154.,1.,16.,452.3063110, &
2.,9.,62.,40.,30.,1.,249.,3.,1.,2.,183.,1.,16.,397.8985779, &
2.,10.,73.,48.,37.,2.,330.,7.,3.,2.,0.,2.,17.,296.9186893, &
2.,11.,73.,48.,37.,2.,358.,7.,3.,2.,0.,2.,17.,650.4114446, &
2.,12.,73.,48.,37.,2.,395.,7.,3.,2.,16.,2.,17.,629.0879334, &
2.,13.,73.,48.,37.,2.,423.,7.,3.,2.,44.,2.,17.,652.3509814, &
2.,14.,73.,48.,37.,2.,451.,7.,3.,2.,72.,2.,17.,646.4552580, &
2.,15.,73.,48.,37.,2.,480.,7.,3.,2.,101.,2.,17.,574.9266523, &
2.,16.,73.,48.,37.,2.,512.,7.,3.,2.,133.,2.,17.,566.6593253, &
2.,17.,73.,48.,37.,2.,541.,7.,3.,2.,162.,2.,17.,533.4725265, &
2.,18.,73.,48.,37.,2.,571.,7.,3.,2.,192.,2.,17.,528.8640179, &
2.,19.,81.,54.,43.,3.,655.,11.,5.,2.,0.,3.,18.,353.0435557, &
2.,20.,81.,54.,43.,3.,684.,11.,5.,2.,0.,3.,18.,604.5727712, &
2.,21.,81.,54.,43.,3.,721.,11.,5.,2.,27.,3.,18.,594.6073949, &
2.,22.,81.,54.,43.,3.,753.,11.,5.,2.,59.,3.,18.,643.0839868, &
2.,23.,81.,54.,43.,3.,781.,11.,5.,2.,87.,3.,18.,644.6999980, &
2.,24.,81.,54.,43.,3.,811.,11.,5.,2.,117.,3.,18.,584.1281864, &
2.,25.,81.,54.,43.,3.,843.,11.,5.,2.,149.,3.,18.,607.2354714, &
2.,26.,81.,54.,43.,3.,872.,11.,5.,2.,178.,3.,18.,584.0046535, &
2.,27.,81.,54.,43.,3.,900.,11.,5.,2.,207.,3.,18.,554.1863141, &
3.,98.,60.,39.,30.,10.,28.,1.,1.,21.,0.,1.,16.,163.7248528, &
3.,99.,60.,39.,30.,10.,57.,1.,1.,21.,0.,1.,16.,203.5392723, &
3.,100.,60.,39.,30.,10.,86.,1.,1.,21.,0.,1.,16.,185.5014819, &
3.,101.,60.,39.,30.,10.,128.,1.,1.,21.,18.,1.,16.,182.0294770, &
3.,102.,60.,39.,30.,10.,156.,1.,1.,21.,46.,1.,16.,191.9161088, &
3.,103.,60.,39.,30.,10.,184.,1.,1.,21.,74.,1.,16.,220.1047668, &
3.,104.,60.,39.,30.,10.,217.,1.,1.,21.,107.,1.,16.,233.7994455, &
3.,105.,60.,39.,30.,10.,247.,1.,1.,21.,137.,1.,16.,260.9411912, &
3.,106.,60.,39.,30.,10.,276.,1.,1.,21.,166.,1.,16.,281.6891974, &
3.,107.,60.,39.,30.,10.,310.,1.,1.,21.,200.,1.,16.,308.5365677, &
3.,108.,79.,51.,40.,14.,342.,7.,2.,21.,0.,2.,18.,319.5569894, &
3.,109.,79.,51.,40.,14.,374.,7.,2.,21.,0.,2.,18.,223.0445005, &
3.,110.,79.,51.,40.,14.,411.,7.,2.,21.,0.,2.,18.,221.0397597, &
3.,111.,79.,51.,40.,14.,440.,7.,2.,21.,0.,2.,18.,215.2311555, &
3.,112.,79.,51.,40.,14.,472.,7.,2.,21.,0.,2.,18.,214.8889595, &
3.,113.,79.,51.,40.,14.,502.,7.,2.,21.,0.,2.,18.,217.2286089, &
3.,114.,79.,51.,40.,14.,531.,7.,2.,21.,19.,2.,18.,263.0485508, &
3.,115.,79.,51.,40.,14.,564.,7.,2.,21.,52.,2.,18.,215.7133804, &
3.,116.,79.,51.,40.,14.,622.,7.,2.,21.,115.,2.,18.,227.9440478, &
4.,98.,60.,39.,30.,10.,30.,1.,1.,22.,0.,1.,16.,385.9091690, &
4.,99.,60.,39.,30.,10.,59.,1.,1.,22.,0.,1.,16.,493.4467048, &
4.,100.,60.,39.,30.,10.,88.,1.,1.,22.,0.,1.,16.,457.4634535, &
4.,101.,60.,39.,30.,10.,130.,1.,1.,22.,18.,1.,16.,464.6963764, &
4.,102.,60.,39.,30.,10.,158.,1.,1.,22.,46.,1.,16.,453.0225033, &
4.,103.,60.,39.,30.,10.,186.,1.,1.,22.,74.,1.,16.,492.1058499, &
4.,104.,60.,39.,30.,10.,219.,1.,1.,22.,107.,1.,16.,473.4442605, &
4.,105.,60.,39.,30.,10.,249.,1.,1.,22.,137.,1.,16.,462.7834378, &
4.,106.,60.,39.,30.,10.,278.,1.,1.,22.,166.,1.,16.,472.9760144, &
4.,107.,60.,39.,30.,10.,312.,1.,1.,22.,200.,1.,16.,511.1238621, &
4.,108.,79.,51.,40.,14.,342.,7.,2.,22.,0.,2.,18.,544.9714596, &
4.,109.,79.,51.,40.,14.,374.,7.,2.,22.,0.,2.,18.,541.7719982, &
4.,110.,79.,51.,40.,14.,411.,7.,2.,22.,0.,2.,18.,589.2739131, &
4.,111.,79.,51.,40.,14.,440.,7.,2.,22.,0.,2.,18.,509.4725033, &
4.,112.,79.,51.,40.,14.,472.,7.,2.,22.,30.,2.,18.,533.5697371, &
4.,113.,79.,51.,40.,14.,502.,7.,2.,22.,60.,2.,18.,501.5968797, &
4.,114.,79.,51.,40.,14.,531.,7.,2.,22.,89.,2.,18.,517.1689298, &
4.,115.,79.,51.,40.,14.,564.,7.,2.,22.,122.,2.,18.,511.7383576, &
4.,116.,79.,51.,40.,14.,622.,7.,2.,22.,185.,2.,18.,481.8987888, &
5.,98.,60.,39.,30.,10.,33.,1.,1.,23.,0.,1.,16.,168.9092787, &
5.,99.,60.,39.,30.,10.,62.,1.,1.,23.,0.,1.,16.,234.3615400, &
5.,100.,60.,39.,30.,10.,91.,1.,1.,23.,0.,1.,16.,248.0502428, &
5.,101.,60.,39.,30.,10.,133.,1.,1.,23.,8.,1.,16.,214.7452577, &
5.,102.,60.,39.,30.,10.,161.,1.,1.,23.,36.,1.,16.,210.9344623, &
5.,103.,60.,39.,30.,10.,189.,1.,1.,23.,64.,1.,16.,277.1039614, &
5.,104.,60.,39.,30.,10.,222.,1.,1.,23.,97.,1.,16.,258.0742928, &
5.,105.,60.,39.,30.,10.,252.,1.,1.,23.,127.,1.,16.,245.3979418, &
5.,106.,60.,39.,30.,10.,281.,1.,1.,23.,156.,1.,16.,230.4785225 &
/), (/ size(datafile, 2), size(datafile, 1) /) ))
call cpu_time(start)
call pred%release()
call pred%init(14)
call compr%setcompress(100*14)
do i=1,100
valtab(:)=datafile(i,:)
call compress64(compr,pred,14,valtab)
end do
call cpu_time(finish)
print '("Time Compress= ",f6.3," seconds."," NFLOT = ",I7)',finish-start
print *," => RATIO =",compr%ratio()
start=finish
call compr%rewind(pred)
do i=1,100
call uncompress64(compr,pred,14,valtab)
if ( count(datafile(i,:) == valtab) /= 14 ) then
call compr%info(6)
write (0,*) "false : val=",valtab," expected ",datafile(i,:), " iloop=",i
stop
end if
end do
write (*,*) "[Ok]"
call cpu_time(finish)
print '("Time Decompr= ",f6.3," seconds."," NFLOT = ",I7)',finish-start
call compr%release()
call pred%release()
deallocate(datafile)
end subroutine test_file
end module compress_fpd
Add a new version
You can submit a new version of this snippet if you have modified it and you feel it is appropriate to share with others.