mirror of https://github.com/ecmwf/eccodes.git
108 lines
3.5 KiB
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;
|
|
}
|