mirror of https://github.com/ecmwf/eccodes.git
230 lines
7.5 KiB
C
230 lines
7.5 KiB
C
/*
|
|
* Copyright 2005-2017 ECMWF.
|
|
*
|
|
* This software is licensed under the terms of the Apache Licence Version 2.0
|
|
* which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
|
|
*
|
|
* In applying this licence, ECMWF does not waive the privileges and immunities granted to it by
|
|
* virtue of its status as an intergovernmental organisation nor does it submit to any jurisdiction.
|
|
*/
|
|
|
|
/***************************************************************************
|
|
* Enrico Fucile - 19.06.2007 *
|
|
* *
|
|
***************************************************************************/
|
|
/**
|
|
* decode an array of n_vals values from a octet-stream
|
|
*
|
|
* @param p input bitstream, for technical reasons put into octets
|
|
* @param bitp current position in the bitstream
|
|
* @param bitsPerValue number of bits needed to build a number (e.g. 8=byte, 16=short, 32=int, but also other sizes allowed)
|
|
* @param n_vals number of values to decode
|
|
* @param val output, values encoded as 32/64bit numbers
|
|
*/
|
|
int grib_decode_long_array(const unsigned char* p, long *bitp, long bitsPerValue,
|
|
size_t n_vals,long* val)
|
|
{
|
|
unsigned long mask = BIT_MASK(bitsPerValue);
|
|
|
|
/* pi: position of bitp in p[]. >>3 == /8 */
|
|
long pi = *bitp / 8;
|
|
size_t i;
|
|
/* number of useful bits in current byte */
|
|
int usefulBitsInByte = 8-(*bitp & 7);
|
|
for(i=0;i < n_vals;i++) {
|
|
/* read at least enough bits (byte by byte) from input */
|
|
long bitsToRead = bitsPerValue;
|
|
long ret = 0;
|
|
while (bitsToRead > 0) {
|
|
ret <<= 8;
|
|
/* ret += p[pi]; */
|
|
/* Assert( (ret & p[pi]) == 0 ); */
|
|
ret = ret | p[pi];
|
|
pi++;
|
|
bitsToRead -= usefulBitsInByte;
|
|
usefulBitsInByte = 8;
|
|
}
|
|
*bitp += bitsPerValue;
|
|
/*fprintf(stderr, "%d %d %d %d %d\n", bitsPerValue, *bitp, pi, ret, bitsToRead);*/
|
|
/* bitsToRead might now be negative (too many bits read) */
|
|
/* remove those which are too much */
|
|
ret >>= -1*bitsToRead;
|
|
/* remove leading bits (from previous value) */
|
|
ret &= mask;
|
|
val[i] = ret;
|
|
|
|
usefulBitsInByte = -1*bitsToRead; /* prepare for next round */
|
|
if (usefulBitsInByte > 0) {
|
|
pi--; /* reread the current byte */
|
|
} else {
|
|
usefulBitsInByte = 8; /* start with next full byte */
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* decode an array of n_vals values from an octet-bitstream to double-representation
|
|
*
|
|
* @param p input bitstream, for technical reasons put into octets
|
|
* @param bitp current position in the bitstream
|
|
* @param bitsPerValue number of bits needed to build a number (e.g. 8=byte, 16=short, 32=int, but also other sizes allowed)
|
|
* @param n_vals number of values to decode
|
|
* @param val output, values encoded as 32/64bit numbers
|
|
*/
|
|
int grib_decode_double_array(const unsigned char* p, long *bitp, long bitsPerValue,
|
|
double reference_value,double s,double d,
|
|
size_t n_vals,double* val)
|
|
{
|
|
long i=0;
|
|
unsigned long lvalue = 0;
|
|
double x;
|
|
|
|
#if 0
|
|
/* slow reference code */
|
|
int j=0;
|
|
for(i=0;i < n_vals;i++) {
|
|
lvalue=0;
|
|
for(j=0; j< bitsPerValue;j++){
|
|
lvalue <<= 1;
|
|
if(grib_get_bit( p, *bitp)) lvalue += 1;
|
|
*bitp += 1;
|
|
}
|
|
x=((lvalue*s)+reference_value)*d;
|
|
val[i] = (double)x;
|
|
}
|
|
#endif
|
|
if (bitsPerValue%8 == 0)
|
|
{
|
|
/* See ECC-386 */
|
|
int bc;
|
|
int l = bitsPerValue/8;
|
|
size_t o = 0;
|
|
|
|
for(i=0;i < n_vals;i++)
|
|
{
|
|
lvalue = 0;
|
|
lvalue <<= 8;
|
|
lvalue |= p[o++] ;
|
|
|
|
for ( bc=1; bc<l; bc++ )
|
|
{
|
|
lvalue <<= 8;
|
|
lvalue |= p[o++] ;
|
|
}
|
|
x=((lvalue*s)+reference_value)*d;
|
|
val[i] = (double)x;
|
|
/* *bitp += bitsPerValue * n_vals; */
|
|
}
|
|
}
|
|
else
|
|
{
|
|
unsigned long mask = BIT_MASK(bitsPerValue);
|
|
|
|
/* pi: position of bitp in p[]. >>3 == /8 */
|
|
long pi = *bitp / 8;
|
|
/* some bits might of the current byte at pi might be used */
|
|
/* by the previous number usefulBitsInByte gives remaining unused bits */
|
|
/* number of useful bits in current byte */
|
|
int usefulBitsInByte = 8-(*bitp & 7);
|
|
for(i=0;i < n_vals;i++) {
|
|
/* value read as long */
|
|
long bitsToRead = 0;
|
|
lvalue = 0;
|
|
bitsToRead = bitsPerValue;
|
|
/* read one byte after the other to lvalue until >= bitsPerValue are read */
|
|
while (bitsToRead > 0) {
|
|
lvalue <<= 8;
|
|
lvalue += p[pi];
|
|
pi++;
|
|
bitsToRead -= usefulBitsInByte;
|
|
usefulBitsInByte = 8;
|
|
}
|
|
*bitp += bitsPerValue;
|
|
/* bitsToRead is now <= 0, remove the last bits */
|
|
lvalue >>= -1*bitsToRead;
|
|
/* set leading bits to 0 - removing bits used for previous number */
|
|
lvalue &= mask;
|
|
|
|
usefulBitsInByte = -1*bitsToRead; /* prepare for next round */
|
|
if (usefulBitsInByte > 0) {
|
|
pi--; /* reread the current byte */
|
|
} else {
|
|
usefulBitsInByte = 8; /* start with next full byte */
|
|
}
|
|
/* scaling and move value to output */
|
|
x=((lvalue*s)+reference_value)*d;
|
|
val[i] = (double)x;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int grib_decode_double_array_complex(const unsigned char* p, long *bitp, long nbits,double reference_value,double s,double* d,size_t size,double* val)
|
|
{
|
|
return GRIB_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
int grib_encode_long_array(size_t n_vals,const long* val,long bits_per_value,unsigned char* p,long *off)
|
|
{
|
|
size_t i=0;
|
|
unsigned long unsigned_val=0;
|
|
unsigned char *encoded=p;
|
|
if(bits_per_value%8){
|
|
for(i=0;i< n_vals;i++){
|
|
unsigned_val=val[i];
|
|
grib_encode_unsigned_longb(encoded, unsigned_val, off , bits_per_value);
|
|
}
|
|
} else{
|
|
for(i=0;i< n_vals;i++){
|
|
int blen=0;
|
|
blen = bits_per_value;
|
|
unsigned_val = val[i];
|
|
while(blen >= 8)
|
|
{
|
|
blen -= 8;
|
|
*encoded = (unsigned_val >> blen);
|
|
encoded++;
|
|
*off+=8;
|
|
}
|
|
}
|
|
}
|
|
return GRIB_SUCCESS;
|
|
}
|
|
|
|
int grib_encode_double_array(size_t n_vals,const double* val,long bits_per_value,double reference_value,double d,double divisor,unsigned char* p,long *off)
|
|
{
|
|
size_t i=0;
|
|
unsigned long unsigned_val=0;
|
|
unsigned char *encoded=p;
|
|
double x;
|
|
if(bits_per_value%8){
|
|
for(i=0;i< n_vals;i++){
|
|
x=(((val[i]*d)-reference_value)*divisor)+0.5;
|
|
unsigned_val = (unsigned long)x;
|
|
grib_encode_unsigned_longb(encoded, unsigned_val, off , bits_per_value);
|
|
}
|
|
} else{
|
|
for(i=0;i< n_vals;i++){
|
|
int blen=0;
|
|
blen = bits_per_value;
|
|
x = ((((val[i]*d)-reference_value)*divisor)+0.5);
|
|
unsigned_val = (unsigned long)x;
|
|
while(blen >= 8)
|
|
{
|
|
blen -= 8;
|
|
*encoded = (unsigned_val >> blen);
|
|
encoded++;
|
|
*off+=8;
|
|
}
|
|
}
|
|
}
|
|
return GRIB_SUCCESS;
|
|
}
|
|
|
|
int grib_encode_double_array_complex(size_t n_vals,double* val,long nbits,double reference_value,
|
|
double* scal,double d,double divisor,unsigned char* p,long *bitp)
|
|
{
|
|
return GRIB_NOT_IMPLEMENTED;
|
|
}
|