mirror of https://github.com/ecmwf/eccodes.git
300 lines
9.2 KiB
C
300 lines
9.2 KiB
C
/*
|
|
* (C) Copyright 2005- 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.
|
|
*/
|
|
|
|
int grib_decode_long_array(const unsigned char* p, long* bitp, long bitsPerValue,
|
|
size_t n_vals, long* val)
|
|
{
|
|
long i = 0;
|
|
unsigned long lvalue = 0;
|
|
|
|
if (bitsPerValue % 8) {
|
|
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;
|
|
}
|
|
val[i] = lvalue;
|
|
}
|
|
}
|
|
else {
|
|
int bc;
|
|
int l = bitsPerValue / 8;
|
|
size_t o = *bitp / 8;
|
|
|
|
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++];
|
|
}
|
|
val[i] = lvalue;
|
|
}
|
|
*bitp += bitsPerValue * n_vals;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
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 (bitsPerValue % 8) {
|
|
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;
|
|
}
|
|
}
|
|
else {
|
|
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;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* code from grib_bits_fast_big_endian_simple.c */
|
|
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)
|
|
{
|
|
long i = 0;
|
|
long countOfLeftmostBits = 0, leftmostBits = 0;
|
|
long startBit;
|
|
long remainingBits = nbits;
|
|
long* pp = (long*)p;
|
|
int inited = 0;
|
|
unsigned long uval = 0;
|
|
|
|
startBit = *bitp;
|
|
remainingBits = nbits;
|
|
if (startBit >= max_nbits) {
|
|
pp += startBit / max_nbits;
|
|
startBit %= max_nbits;
|
|
}
|
|
|
|
if ((max_nbits % nbits == 0) && (*bitp % nbits == 0)) {
|
|
for (i = 0; i < size; i++) {
|
|
if (startBit == max_nbits) {
|
|
startBit = 0;
|
|
pp++;
|
|
}
|
|
|
|
val[i] = VALUE(*pp, startBit, remainingBits);
|
|
val[i] = ((((val[i]) * s) + reference_value) * d[i / 2]);
|
|
startBit += remainingBits;
|
|
remainingBits = nbits;
|
|
}
|
|
}
|
|
else {
|
|
for (i = 0; i < size; i++) {
|
|
countOfLeftmostBits = startBit + remainingBits;
|
|
if (countOfLeftmostBits > max_nbits) {
|
|
countOfLeftmostBits = max_nbits - startBit;
|
|
remainingBits -= countOfLeftmostBits;
|
|
leftmostBits = (VALUE(*pp, startBit, countOfLeftmostBits)) << remainingBits;
|
|
startBit = 0;
|
|
pp++;
|
|
}
|
|
else
|
|
leftmostBits = 0;
|
|
|
|
val[i] = leftmostBits + (VALUE(*pp, startBit, remainingBits));
|
|
val[i] = ((((val[i]) * s) + reference_value) * d[i / 2]);
|
|
startBit += remainingBits;
|
|
remainingBits = nbits;
|
|
}
|
|
}
|
|
|
|
*bitp += size * nbits;
|
|
|
|
return GRIB_SUCCESS;
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
#define U_BYTEORDER \
|
|
static union \
|
|
{ \
|
|
unsigned long l; \
|
|
unsigned char c[sizeof(long)]; \
|
|
} u_byteorder = { 1 }
|
|
#define IS_BIGENDIAN() (u_byteorder.c[sizeof(long) - 1])
|
|
#define GRIBPACK unsigned char
|
|
#define Error(x, y) fprintf(stderr, x, y)
|
|
#define restrict
|
|
|
|
#include "encode_double_array.c"
|
|
|
|
#undef U_BYTEORDER
|
|
#undef IS_BIGENDIAN
|
|
#undef GRIBPACK
|
|
#undef Error
|
|
#undef restrict
|
|
|
|
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)
|
|
{
|
|
if (fabs(d - 1) > 0) /* d != 1 */
|
|
{
|
|
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;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
#if defined(_ARCH_PWR6)
|
|
encode_double_array_unrolled(bits_per_value, 0, n_vals, p, val, reference_value, divisor, off);
|
|
#else
|
|
encode_double_array_byte(bits_per_value, 0, n_vals, p, val, reference_value, divisor, off);
|
|
#endif
|
|
}
|
|
|
|
return GRIB_SUCCESS;
|
|
}
|
|
|
|
/* code from grib_bits_fast_big_endian_simple.c */
|
|
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)
|
|
{
|
|
long* destination = (long*)p;
|
|
double* v = val;
|
|
long countOfLeftmostBits = 0, startBit = 0, remainingBits = 0, rightmostBits = 0;
|
|
unsigned long uval = 0;
|
|
size_t i = 0;
|
|
|
|
startBit = *bitp;
|
|
remainingBits = nbits;
|
|
|
|
if (startBit >= max_nbits) {
|
|
destination += startBit / max_nbits;
|
|
startBit %= max_nbits;
|
|
}
|
|
|
|
if ((max_nbits % nbits == 0) && (*bitp % nbits == 0)) {
|
|
for (i = 0; i < n_vals; i++) {
|
|
uval = (unsigned long)(((((*v) * d * scal[i / 2]) - reference_value) * divisor) + 0.5);
|
|
if (startBit == max_nbits) {
|
|
startBit = 0;
|
|
destination++;
|
|
}
|
|
|
|
rightmostBits = VALUE(uval, max_nbits - remainingBits, remainingBits);
|
|
*destination = ((*destination) & ~MASKVALUE(startBit, remainingBits)) + (rightmostBits << max_nbits - (remainingBits + startBit));
|
|
startBit += remainingBits;
|
|
remainingBits = nbits;
|
|
|
|
v++;
|
|
}
|
|
}
|
|
else {
|
|
for (i = 0; i < n_vals; i++) {
|
|
countOfLeftmostBits = startBit + remainingBits;
|
|
uval = (unsigned long)(((((*v) * d * scal[i / 2]) - reference_value) * divisor) + 0.5);
|
|
if (countOfLeftmostBits > max_nbits) {
|
|
countOfLeftmostBits = max_nbits - startBit;
|
|
startBit = max_nbits - remainingBits;
|
|
remainingBits -= countOfLeftmostBits;
|
|
*destination = (((*destination) >> countOfLeftmostBits) << countOfLeftmostBits) + (VALUE(uval, startBit, countOfLeftmostBits));
|
|
startBit = 0;
|
|
destination++;
|
|
}
|
|
|
|
rightmostBits = VALUE(uval, max_nbits - remainingBits, remainingBits);
|
|
*destination = ((*destination) & ~MASKVALUE(startBit, remainingBits)) + (rightmostBits << max_nbits - (remainingBits + startBit));
|
|
startBit += remainingBits;
|
|
remainingBits = nbits;
|
|
|
|
v++;
|
|
}
|
|
}
|
|
|
|
*bitp += n_vals * nbits;
|
|
|
|
return 0;
|
|
}
|