diff --git a/ext/bg/bg.c b/ext/bg/bg.c new file mode 100644 index 0000000..dc5a714 --- /dev/null +++ b/ext/bg/bg.c @@ -0,0 +1,185 @@ +#include "bg.h" +#include +#include +#include +#include + +int versionNumber[4] = {BG_VER_MAJOR,BG_VER_MINOR,BG_VER_BUILD,BG_VER_REVISION}; +//int BG_SIZE_TYPE = 8; + +int dataEndianType = LITTLE_ENDIAN_DATA; //*endian type of the data read from disk +int sysEndianType; //*sysEndianType is actually set automatically. + +//the confparams should be separate between compression and decopmression, in case of mutual-affection when calling compression/decompression alternatively +bg_params *confparams_cpr = NULL; //used for compression +bg_params *confparams_dec = NULL; //used for decompression + +bg_exedata *exe_params = NULL; + +int bgMode_libpressio = BITGROOM; +int errorControlMode_libpressio = BG_NSD; +int nsd_libpressio = 5; +int dsd_libpressio = 5; + +#if 0 +unsigned char *BG_compress(int dataType, void *data, size_t *outSize, size_t nbEle) +{ + return BG_compress_args(dataType, data, outSize, confparams_cpr->bgMode, confparams_cpr->errorControlMode, confparams_cpr->NSD, confparams_cpr->DSD, nbEle); +} +#endif + +unsigned char* BG_compress_args(int dataType, void *data, size_t *outSize, int bgMode, int errorControlMode, int nsd, int dsd, size_t nbEle, unsigned char *data_) +{ + + int dataTypeLen = dataType==BG_FLOAT?sizeof(float):sizeof(double); + + size_t bufferSize = dataTypeLen*nbEle; + + const double bit_per_dcm_dgt_prc=M_LN10/M_LN2; /* 3.32 [frc] Bits per decimal digit of precision */ + //const double dcm_per_bit_dgt_prc=M_LN2/M_LN10; /* 0.301 [frc] Bits per decimal digit of precision */ + const int bit_xpl_nbr_sgn_flt=23; /* [nbr] Bits 0-22 of SP significands are explicit. Bit 23 is implicitly 1. */ + const int bit_xpl_nbr_sgn_dbl=53; /* [nbr] Bits 0-52 of DP significands are explicit. Bit 53 is implicitly 1. */ + //const int ieee_xpn_fst_flt=127; /* [nbr] IEEE "exponent bias" = actual exponent minus stored exponent */ + + double prc_bnr_xct; /* [nbr] Binary digits of precision, exact */ + + int bit_xpl_nbr_sgn=int_CEWI; /* [nbr] Number of explicit bits in significand */ + int bit_xpl_nbr_zro; /* [nbr] Number of explicit bits to zero */ + + long idx; + + unsigned int *u32_ptr; + unsigned int msk_f32_u32_zro; + unsigned int msk_f32_u32_one; + //unsigned int msk_f32_u32_hshv; + unsigned long long *u64_ptr; + unsigned long long msk_f64_u64_zro; + unsigned long long msk_f64_u64_one; + //unsigned long int msk_f64_u64_hshv; + unsigned short prc_bnr_ceil; /* [nbr] Exact binary digits of precision rounded-up */ + unsigned short prc_bnr_xpl_rqr; /* [nbr] Explicitly represented binary digits required to retain */ + + if(errorControlMode == BG_NSD && (nsd < 0 || nsd >16)) + { + printf("Error: wrong nsd input\n"); + return NULL; + } + + /* How many bits to preserve? */ + prc_bnr_xct=nsd*bit_per_dcm_dgt_prc; + /* Be conservative, round upwards */ + prc_bnr_ceil=(unsigned short)ceil(prc_bnr_xct); + /* First bit is implicit not explicit but corner cases prevent our taking advantage of this */ + //prc_bnr_xpl_rqr=prc_bnr_ceil-1; + //prc_bnr_xpl_rqr=prc_bnr_ceil; + prc_bnr_xpl_rqr=prc_bnr_ceil+1; + + //unsigned char* data_ = (unsigned char*)malloc(bufferSize); + memcpy(data_, data, bufferSize); + + if(dataType == BG_DOUBLE) prc_bnr_xpl_rqr++; /* Seems necessary for double-precision ppc=array(1.234567,1.0e-6,$dmn) */ + + if(!(dataType == BG_FLOAT && prc_bnr_xpl_rqr >= bit_xpl_nbr_sgn_flt) || (dataType == BG_DOUBLE && prc_bnr_xpl_rqr >= bit_xpl_nbr_sgn_dbl)) //required # bits is greater than the full length of bits + { + if(dataType==BG_FLOAT) + { + bit_xpl_nbr_sgn=bit_xpl_nbr_sgn_flt; + bit_xpl_nbr_zro=bit_xpl_nbr_sgn-prc_bnr_xpl_rqr; + if(bit_xpl_nbr_zro > bit_xpl_nbr_sgn-NCO_PPC_BIT_XPL_NBR_MIN) + { + printf("Error: bit_xpl_nbr_zro > bit_xpl_nbr_sgn-NCO_PPC_BIT_XPL_NBR_MIN\n"); + return NULL; + } + + u32_ptr = (unsigned int*)data_; + /* Create mask */ + msk_f32_u32_zro=0u; /* Zero all bits */ + msk_f32_u32_zro=~msk_f32_u32_zro; /* Turn all bits to ones */ + /* Bit Shave mask for AND: Left shift zeros into bits to be rounded, leave ones in untouched bits */ + msk_f32_u32_zro <<= bit_xpl_nbr_zro; + /* Bit Set mask for OR: Put ones into bits to be set, zeros in untouched bits */ + msk_f32_u32_one=~msk_f32_u32_zro; + //msk_f32_u32_hshv=msk_f32_u32_one & (msk_f32_u32_zro >> 1); /* Set one bit: the MSB of LSBs */ + switch(bgMode) + { + case BITGROOM: + for(idx=0L;idx bit_xpl_nbr_sgn-NCO_PPC_BIT_XPL_NBR_MIN) + { + printf("Error: bit_xpl_nbr_zro > bit_xpl_nbr_sgn-NCO_PPC_BIT_XPL_NBR_MIN\n"); + return NULL; + } + + u64_ptr=(unsigned long int*)data_; + /* Create mask */ + msk_f64_u64_zro=0ul; /* Zero all bits */ + msk_f64_u64_zro=~msk_f64_u64_zro; /* Turn all bits to ones */ + /* Bit Shave mask for AND: Left shift zeros into bits to be rounded, leave ones in untouched bits */ + msk_f64_u64_zro <<= bit_xpl_nbr_zro; + /* Bit Set mask for OR: Put ones into bits to be set, zeros in untouched bits */ + msk_f64_u64_one=~msk_f64_u64_zro; + //msk_f64_u64_hshv=msk_f64_u64_one & (msk_f64_u64_zro >> 1); /* Set one bit: the MSB of LSBs */ + switch(bgMode) + { + case BITGROOM: + for(idx=0L;idx