eccodes/src/grib_2order_packer_simple.c

108 lines
3.5 KiB
C

/*
* Copyright 2005-2018 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.
*/
#include "grib_api_internal.h"
static unsigned long calc_pow_2(unsigned long op)
{
unsigned long a = 1;
while(op--) a*=2;
return a;
}
static int calc_bits_needed(unsigned long spread)
{
int nbit = 0;
if (spread == 0) return nbit;
while (spread>0){
spread/=2;
nbit++;
}
return nbit;
}
static int find_next_group(const unsigned long* vals, size_t len, unsigned long w, unsigned long l,unsigned long* nbits, unsigned long* groupsize, long* r_val)
{
long lmin = 0;
long lmax = 0;
size_t i = 0;
if (len <=0 ) return GRIB_ARRAY_TOO_SMALL;
lmin = vals[0];
lmax = lmin;
while(i < len) {
if (vals[i] > lmax) lmax = vals[i];
else if (vals[i] < lmin) lmin = vals[i];
Assert((lmax-lmin) >= 0);
*nbits = calc_bits_needed(lmax-lmin);
*r_val = lmin;
i++;
*groupsize = i;
if(*groupsize > l-2) return GRIB_SUCCESS;
if(*nbits > w-2) return GRIB_SUCCESS;
}
return GRIB_SUCCESS;
}
void grib_free_second_order_groups(grib_context *c,second_order_packed* sp)
{
if(!sp) return;
grib_context_free(c,sp->array_of_group_size);
grib_context_free(c,sp->array_of_group_refs);
grib_context_free(c,sp->array_of_group_width);
grib_context_free(c,sp);
}
second_order_packed* grib_get_second_order_groups(grib_context *c, const unsigned long* vals, size_t len)
{
second_order_packed* s = (second_order_packed*)grib_context_malloc_clear(c,sizeof(second_order_packed));
const unsigned long* group_val = vals;
size_t nv = len;
size_t i = 0;
unsigned long nbit_per_group;
unsigned long size_of_group;
long ref_of_group;
s->packed_byte_count = 0;
s->nbits_per_group_size = 6;
s->nbits_per_widths = 4;
s->size_of_group_array = 0;
while(find_next_group(group_val, nv, calc_pow_2(s->nbits_per_widths), calc_pow_2(s->nbits_per_group_size ), &nbit_per_group, &size_of_group, &ref_of_group) == GRIB_SUCCESS){
s->size_of_group_array += 1;
nv -= size_of_group;
group_val += size_of_group;
s->packed_byte_count += size_of_group*nbit_per_group;
}
s->packed_byte_count = ((s->packed_byte_count+7)/8);
s->array_of_group_size = (unsigned long*)grib_context_malloc_clear(c,sizeof(unsigned long)*s->size_of_group_array);
s->array_of_group_width = (unsigned long*)grib_context_malloc_clear(c,sizeof(unsigned long)*s->size_of_group_array);
s->array_of_group_refs = (long*)grib_context_malloc_clear(c,sizeof( long)*s->size_of_group_array);
group_val = vals;
nv = len;
while(find_next_group(group_val, nv, calc_pow_2(s->nbits_per_widths), calc_pow_2(s->nbits_per_group_size ), &nbit_per_group, &size_of_group, &ref_of_group) == GRIB_SUCCESS){
nv -= size_of_group;
group_val += size_of_group;
Assert(i<s->size_of_group_array);
s->array_of_group_size[i] = size_of_group;
s->array_of_group_width[i] = nbit_per_group;
s->array_of_group_refs[i] = ref_of_group;
i++;
}
return s;
}