Beispiel #1
0
unsigned long grib_decode_unsigned_long(const unsigned char* p, long *bitp, long nbits)
{
    int i;
    long ret = 0;
    long o = *bitp/8;
    int l = nbits/8;

    if (nbits==0) return 0;

    if(nbits > max_nbits)
    {
        int bits = nbits;
        int mod = bits % max_nbits;

        if(mod != 0)
        {
            int e=grib_decode_unsigned_long(p,bitp,mod);
            Assert( e == 0);
            bits -= mod;
        }

        while(bits > max_nbits)
        {
            int e=grib_decode_unsigned_long(p,bitp,max_nbits);
            Assert( e == 0);
            bits -= max_nbits;
        }

        return grib_decode_unsigned_long(p,bitp,bits);
    }

    if((nbits%8 > 0)||(*bitp%8 > 0)) {
        for(i=0; i< nbits;i++){
            ret <<= 1;
            if(grib_get_bit( p, *bitp)) ret += 1;
            *bitp += 1;
        }
        return ret;
    }

    ret  <<= 8;
    ret |= p[o++] ;

    for ( i=1; i<l; i++ )
    {
        ret <<= 8;
        ret |= p[o++] ;
    }
    *bitp += nbits;

    return ret;
}
static int    unpack_long   (grib_accessor* a, long* val, size_t *len)
{
  grib_accessor_codetable* self = (grib_accessor_codetable*)a;
  unsigned long rlen = grib_value_count(a);
  unsigned long i = 0;
  long pos = a->offset*8;

  if(!self->table) self->table = load_table(self);

  if(*len < rlen)
  {
    grib_context_log(a->parent->h->context, GRIB_LOG_ERROR, " wrong size (%ld) for %s it contains %d values ",*len, a->name , rlen);
    *len = 0;
    return GRIB_ARRAY_TOO_SMALL;
  }

  if (a->flags & GRIB_ACCESSOR_FLAG_TRANSIENT) {
    *val=a->vvalue->lval;
    *len=1;
    return GRIB_SUCCESS;
  }

  for(i=0; i< rlen;i++){
    val[i] = (long)grib_decode_unsigned_long(a->parent->h->buffer->data , &pos, self->nbytes*8);
  }

  *len = rlen;
  return GRIB_SUCCESS;
}
static int unpack_long(grib_accessor* a, long* val, size_t *len)
{
  grib_accessor_lookup* al = (grib_accessor_lookup*)a;
  grib_handle *h = a->parent->h;


  long pos = (a->offset+al->loffset)*8;


  if(len[0] < 1)
  {
    grib_context_log(a->parent->h->context, GRIB_LOG_ERROR, "Wrong size for %s it contains %d values ", a->name , 1 );
    len[0] = 0;
    return GRIB_ARRAY_TOO_SMALL;
  }

  /* This is used when reparsing or rebuilding */
  if(h->loader) {
    Assert(*len == 1);
    return h->loader->lookup_long(h->context,h->loader,a->name,val);
  }

  val[0] = grib_decode_unsigned_long(h->buffer->data , &pos, al->llength*8);
  len[0] = 1;

/* printf("lookup: %s %ld %ld\n",a->name,pos/8,val[0]); */

  return GRIB_SUCCESS;

}
static int unpack_double   (grib_accessor* a, double* val, size_t *len)
{
    unsigned long rlen = 0;
    long count=0;
    int err=0;
    unsigned long i = 0;
    long bitp = a->offset*8;

    err=grib_value_count(a,&count);
    if (err) return err;
    rlen=count;

    if(*len < rlen)
    {
        grib_context_log(a->parent->h->context, GRIB_LOG_ERROR, " wrong size (%ld) for %s it contains %d values ", *len,a->name , rlen);
        *len = 0;
        return GRIB_ARRAY_TOO_SMALL;
    }

    for(i=0; i< rlen; i++)
        val[i] = grib_long_to_ibm(grib_decode_unsigned_long(a->parent->h->buffer->data,&bitp,32));

    *len = rlen;
    return GRIB_SUCCESS;
}
static int unpack_double(grib_accessor* a, double* val, size_t *len)
{
    grib_accessor_bits* self = (grib_accessor_bits*)a;
    grib_accessor* x=NULL;
    unsigned char* p=NULL;
    grib_handle* h=grib_handle_of_accessor(a);
    long start,length;
    int ret=0;

    if(*len < 1) return GRIB_WRONG_ARRAY_SIZE;

    start=self->start;
    length=self->len;

    x=grib_find_accessor(grib_handle_of_accessor(a),self->argument);
    if (!x) return GRIB_NOT_FOUND;

    p  = h->buffer->data + grib_byte_offset(x);
    *val=grib_decode_unsigned_long(p,&start,length);

    *val=((long)*val+self->referenceValue)/self->scale;

    *len=1;

    return ret;
}
static int unpack_double_element   (grib_accessor* a, size_t idx, double* val)
{
    long pos = a->offset*8;

    pos+=idx;
    *val = (double)grib_decode_unsigned_long(a->parent->h->buffer->data, &pos,1);

    return GRIB_SUCCESS;
}
int grib_get_g1_message_size(grib_handle* h,grib_accessor* tl,grib_accessor* s4,
                             long* total_length,long* sec4_len)
{
    unsigned long tlen,slen;
    long off;

    if(!tl) return GRIB_NOT_FOUND;
    if(!s4) {
        *sec4_len     = 0;
        off = tl->offset * 8;
        *total_length = grib_decode_unsigned_long(h->buffer->data, &off, tl->length * 8);
        return GRIB_SUCCESS;
    }

    off = tl->offset * 8;
    tlen = grib_decode_unsigned_long(h->buffer->data, &off, tl->length * 8);

    off = s4->offset * 8;
    slen = grib_decode_unsigned_long(h->buffer->data, &off, s4->length * 8);

    /* printf("\nlarge grib tlen=%ld slen=%ld diff=%ld\n",tlen&0x7fffff,slen,tlen-slen); */

    if(slen < 120 && (tlen & 0x800000))
    {
        /* printf("DECODING large grib tlen=%ld slen=%ld\n",tlen,slen); */

        tlen &= 0x7fffff;
        tlen *= 120;
        tlen -= slen;
        tlen += 4;

        slen = tlen - s4->offset - 4; /* 4 is for 7777 */;

        /*printf("DECODING large grib total=%ld section4=%ld\n",tlen,slen);*/
    }

    *total_length = tlen;
    *sec4_len     = slen;

    return GRIB_SUCCESS;
}
static int unpack_long(grib_accessor* a, long* val, size_t *len)
{
    grib_accessor_unsigned* self = (grib_accessor_unsigned*)a;
    long rlen = 0;
    unsigned long i = 0;
    unsigned long missing = 0;
    long count=0;
    int err = 0;
    long pos = a->offset*8;

    err=grib_value_count(a,&count);
    if (err) return err;
    rlen=count;

    if(*len < rlen)
    {
        grib_context_log(a->parent->h->context, GRIB_LOG_ERROR, " wrong size (%ld) for %s it contains %d values ",*len, a->name , rlen);
        *len = 0;
        return GRIB_ARRAY_TOO_SMALL;
    }

    if (a->flags & GRIB_ACCESSOR_FLAG_TRANSIENT) {
        *val=a->vvalue->lval;
        *len=1;
        return GRIB_SUCCESS;
    }

    if(a->flags & GRIB_ACCESSOR_FLAG_CAN_BE_MISSING)
    {
        Assert(self->nbytes <= 4);
        missing = ones[self->nbytes];
    }

    for(i=0; i< rlen;i++){
        val[i] = (long)grib_decode_unsigned_long(a->parent->h->buffer->data , &pos, self->nbytes*8);
        if(missing)
            if(val[i] == missing)
                val[i] = GRIB_MISSING_LONG;
    }

    *len = rlen;
    return GRIB_SUCCESS;
}
static int unpack_long(grib_accessor* a, long* val, size_t *len)
{

  long value = 0;
  long pos = a->offset*8;
  char *intc = NULL;
  char  expver[5];
  char  refexpver[5];
  size_t llen = a->length+1;
  Assert(a->length == 4);

  if(*len < 1)
  {
    grib_context_log(a->parent->h->context, GRIB_LOG_ERROR, "Wrong size for %s it contains %d values ", a->name , 1 );
    *len = 0;
    return GRIB_ARRAY_TOO_SMALL;
  }
  value = grib_decode_unsigned_long(a->parent->h->buffer->data , &pos, a->length*8);

  grib_unpack_string(a, refexpver , &llen);

  /* test for endiannes */
  intc = (char*)&value;

  expver[0] = intc[0];
  expver[1] = intc[1];
  expver[2] = intc[2];
  expver[3] = intc[3];
  expver[4] = 0;

  /* if there is a difference, have to reverse*/
  if(strcmp(refexpver, expver)){
    intc[0] = expver[3];
    intc[1] = expver[2];
    intc[2] = expver[1];
    intc[3] = expver[0];
  }

  *val = value;
  *len = 1;
  return GRIB_SUCCESS;
}
static int value_count(grib_accessor* a,long* count)
{
    int err=0;
    grib_accessor_data_2order_packing* self =  (grib_accessor_data_2order_packing*)a;
    long  two_ordr_spd = 0;
    long  plus1_spd    = 0;
    grib_handle* gh = grib_handle_of_accessor(a);
    unsigned char* buf_size_of_groups = (unsigned char*)gh->buffer->data;
    long octet_start_group = 0;
    long offsetsection = 0;
    long nbits_per_lengths = 0;
    long pointer_of_group_size = 0;
    long p1 = 0;
    long extraValues=0;

    size_t i = 0;

    if((err=grib_get_long_internal(gh,self->two_ordr_spd, &two_ordr_spd)) != GRIB_SUCCESS)
        return err;
    if( (err=grib_get_long_internal(gh,self->plus1_spd, &plus1_spd)) != GRIB_SUCCESS)
        return err;
    if( (err=grib_get_long_internal(gh,self->width_lengths, &nbits_per_lengths)) != GRIB_SUCCESS)
        return err;
    if( (err=grib_get_long_internal(gh,self->offsetsection, &offsetsection)) != GRIB_SUCCESS)
        return err;
    if( (err=grib_get_long_internal(gh,self->octet_start_group, &octet_start_group)) != GRIB_SUCCESS)
        return err;
    if( (err=grib_get_long_internal(gh,self->p1, &p1)) != GRIB_SUCCESS)
        return err;
    if( (err=grib_get_long_internal(gh,self->extraValues, &extraValues)) != GRIB_SUCCESS)
        return err;

    p1+=extraValues*65536;

    buf_size_of_groups +=  offsetsection+(octet_start_group-1);
    *count = two_ordr_spd*2+plus1_spd;

    for(i=0;i < p1;i++)
        *count +=  grib_decode_unsigned_long(buf_size_of_groups,  &pointer_of_group_size, nbits_per_lengths);

    return err;
}
static int    unpack_long   (grib_accessor* a, long* val, size_t *len)
{
  int ret=0;
  grib_accessor_data_2order_packing_count* self =  (grib_accessor_data_2order_packing_count*)a;
  long count = 0;
  long  two_ordr_spd = 0;
  long  plus1_spd    = 0;
  unsigned char* buf_size_of_groups = (unsigned char*)grib_handle_of_accessor(a)->buffer->data;
  long octet_start_group = 0;
  long offsetsection = 0;
  long nbits_per_lengths = 0;
  long pointer_of_group_size = 0;
  long p1 = 0;

  size_t i = 0;

  if ((ret=grib_get_long_internal(grib_handle_of_accessor(a),self->two_ordr_spd, &two_ordr_spd))
       !=GRIB_SUCCESS) return ret;
  if ((ret=grib_get_long_internal(grib_handle_of_accessor(a),self->plus1_spd, &plus1_spd))
       !=GRIB_SUCCESS) return ret;
  if ((ret=grib_get_long_internal(grib_handle_of_accessor(a),self->width_lengths, &nbits_per_lengths))
       !=GRIB_SUCCESS) return ret;
  if ((ret=grib_get_long_internal(grib_handle_of_accessor(a),self->offsetsection, &offsetsection))
       !=GRIB_SUCCESS) return ret;
  if ((ret=grib_get_long_internal(grib_handle_of_accessor(a),self->octet_start_group, &octet_start_group))
       !=GRIB_SUCCESS) return ret;
  if ((ret=grib_get_long_internal(grib_handle_of_accessor(a),self->p1, &p1))
       !=GRIB_SUCCESS) return ret;

  buf_size_of_groups +=  offsetsection+(octet_start_group-1);
  count = two_ordr_spd*2+plus1_spd;

  for(i=0;i < p1;i++)
    count +=  grib_decode_unsigned_long(buf_size_of_groups,  &pointer_of_group_size, nbits_per_lengths);

  *val=count;
  *len=1;
  return GRIB_SUCCESS;
}
static int    unpack_long   (grib_accessor* a, long* val, size_t *len)
{
  grib_accessor_bits* self = (grib_accessor_bits*)a;
  grib_accessor* x=NULL;
  unsigned char* p=NULL;
  grib_handle* h=a->parent->h;
  long start,length;
  int ret=0;

  if(*len < 1) return GRIB_WRONG_ARRAY_SIZE;

  start=self->start;
  length=self->len;
  
  x=grib_find_accessor(a->parent->h,self->argument);
  if (!x) return GRIB_NOT_FOUND;

  p  = h->buffer->data + grib_byte_offset(x);
  *val=grib_decode_unsigned_long(p,&start,length);

  *len=1;

  return ret;
}
static int unpack_double   (grib_accessor* a, double* val, size_t *len)
{
    long pos = a->offset*8;
    long tlen;
    long i;
    int err=0;

    err = grib_value_count(a,&tlen);
    if (err) return err;

    if(*len < tlen)
    {
        grib_context_log(a->parent->h->context, GRIB_LOG_ERROR, "Wrong size for %s it contains %d values ", a->name , tlen );
        *len = 0;
        return GRIB_ARRAY_TOO_SMALL;
    }

    for(i=0;i<tlen;i++)
    {
        val[i] = (double)grib_decode_unsigned_long(a->parent->h->buffer->data, &pos,1);
    }
    *len = tlen;
    return GRIB_SUCCESS;
}
static int  unpack_double(grib_accessor* a, double* val, size_t *len)
{
    grib_accessor_data_complex_packing* self =  (grib_accessor_data_complex_packing*)a;

    size_t i = 0;
    int ret = GRIB_SUCCESS;
    long   hcount = 0;
    long   lcount = 0;
    long   hpos = 0;
    long   lup = 0;
    long   mmax = 0;
    long   n_vals = 0;
    double *scals  = NULL;
    double *pscals=NULL,*pval=NULL;

    double s = 0;
    double d = 0;
    double laplacianOperator = 0;
    unsigned char* buf = NULL;
    unsigned char* hres = NULL;
    unsigned char* lres = NULL;
    unsigned long packed_offset;
    long   lpos = 0;

    long   maxv = 0;
    long   GRIBEX_sh_bug_present =0;
    long ieee_floats  = 0;

    long   offsetdata           = 0;
    long   bits_per_value          = 0;
    double reference_value      = 0;
    long   binary_scale_factor         = 0;
    long   decimal_scale_factor = 0;

    long   sub_j= 0;
    long   sub_k= 0;
    long   sub_m= 0;
    long   pen_j= 0;
    long   pen_k= 0;
    long   pen_m= 0;

    double operat= 0;
    int bytes;
    int err=0;

    decode_float_proc decode_float = NULL;

    err=grib_value_count(a,&n_vals);
    if (err) return err;

    if(*len < n_vals){
        *len = n_vals;
        return GRIB_ARRAY_TOO_SMALL;
    }

    if((ret = grib_get_long_internal(a->parent->h,self->offsetdata,&offsetdata))
            != GRIB_SUCCESS)   return ret;
    if((ret = grib_get_long_internal(a->parent->h,self->bits_per_value,&bits_per_value))
            != GRIB_SUCCESS)   return ret;
    if((ret = grib_get_double_internal(a->parent->h,self->reference_value,&reference_value))
            != GRIB_SUCCESS)   return ret;
    if((ret = grib_get_long_internal(a->parent->h,self->binary_scale_factor,&binary_scale_factor))
            != GRIB_SUCCESS)           return ret;

    if((ret = grib_get_long_internal(a->parent->h,self->decimal_scale_factor,&decimal_scale_factor))
            != GRIB_SUCCESS)
        return ret;

    if((ret = grib_get_long_internal(a->parent->h,self->GRIBEX_sh_bug_present,&GRIBEX_sh_bug_present))
            != GRIB_SUCCESS)
        return ret;

    if((ret = grib_get_long_internal(a->parent->h,self->ieee_floats,&ieee_floats)) != GRIB_SUCCESS)
        return ret;

    if((ret = grib_get_double_internal(a->parent->h,self->laplacianOperator,&laplacianOperator))
            != GRIB_SUCCESS)
        return ret;
    if((ret = grib_get_long_internal(a->parent->h,self->sub_j,&sub_j)) != GRIB_SUCCESS)
        return ret;
    if((ret = grib_get_long_internal(a->parent->h,self->sub_k,&sub_k)) != GRIB_SUCCESS)
        return ret;
    if((ret = grib_get_long_internal(a->parent->h,self->sub_m,&sub_m)) != GRIB_SUCCESS)
        return ret;
    if((ret = grib_get_long_internal(a->parent->h,self->pen_j,&pen_j)) != GRIB_SUCCESS)
        return ret;
    if((ret = grib_get_long_internal(a->parent->h,self->pen_k,&pen_k)) != GRIB_SUCCESS)
        return ret;
    if((ret = grib_get_long_internal(a->parent->h,self->pen_m,&pen_m)) != GRIB_SUCCESS)
        return ret;

    self->dirty=0;

    switch (ieee_floats) {
    case 0:
        decode_float=grib_long_to_ibm;
        bytes=4;
        break;
    case 1:
        decode_float=grib_long_to_ieee;
        bytes=4;
        break;
    case 2:
        decode_float=grib_long_to_ieee64;
        bytes=8;
        break;
    default:
        return GRIB_NOT_IMPLEMENTED;
    }

    Assert (sub_j == sub_k);
    Assert (sub_j == sub_m);
    Assert (pen_j == pen_k);
    Assert (pen_j == pen_m);

    buf = (unsigned char*)a->parent->h->buffer->data;

    maxv = pen_j+1;

    buf  += grib_byte_offset(a);
    hres = buf;
    lres = buf;

    if (pen_j == sub_j) {
        n_vals = (pen_j+1)*(pen_j+2);
        d = grib_power(-decimal_scale_factor,10) ;
        grib_ieee_decode_array(a->parent->h->context,buf,n_vals,bytes,val);
        if (d) {
            for (i=0;i<n_vals;i++) val[i]*=d;
        }
        return 0;
    }

    packed_offset = grib_byte_offset(a) +  4*(sub_k+1)*(sub_k+2);

    lpos = 8*(packed_offset-offsetdata);

    s = grib_power(binary_scale_factor,2);
    d = grib_power(-decimal_scale_factor,10) ;

    scals   = (double*)grib_context_malloc(a->parent->h->context,maxv*sizeof(double));
    Assert(scals);

    scals[0] = 0;
    for(i=1;i<maxv;i++){
        operat = pow(i*(i+1),laplacianOperator);
        if(operat !=  0)
            scals[i] = (1.0/operat);
        else{
            grib_context_log(a->parent->h->context,GRIB_LOG_WARNING,
                    "COMPLEX_PACKING : problem with operator div by zero at index %d of %d \n",
                    i , maxv);
            scals[i] = 0;
        }
    }

    /*
  printf("UNPACKING LAPLACE=%.20f\n",laplacianOperator);

  printf("packed offset=%ld\n",packed_offset);
  for(i=0;i<maxv;i++)
    printf("scals[%d]=%g\n",i,scals[i]);*/

    i=0;

    while(maxv>0)
    {
        lup=mmax;
        if(sub_k>=0)
        {
            for(hcount=0;hcount<sub_k+1;hcount++)
            {
                val[i++] =  decode_float(grib_decode_unsigned_long(hres,&hpos,32))*d;
                val[i++] =  decode_float(grib_decode_unsigned_long(hres,&hpos,32))*d;

                if (GRIBEX_sh_bug_present && hcount==sub_k){
                    /*  bug in ecmwf data, last row (K+1)is scaled but should not */
                    val[i-2] *= scals[lup];
                    val[i-1] *= scals[lup];
                }
                lup++;
            }
            sub_k--;
        }

        pscals=scals+lup;
        pval=val+i;
#if FAST_BIG_ENDIAN
        grib_decode_double_array_complex(lres,
                &lpos,bits_per_value,
                reference_value,s,pscals,(maxv-hcount)*2,pval);
        i+=(maxv-hcount)*2;
#else
        (void)pscals; /* suppress gcc warning */
        (void)pval;   /* suppress gcc warning */
        for(lcount=hcount; lcount < maxv ; lcount++)
        {
            val[i++] =  (double) ((grib_decode_unsigned_long(lres, &lpos,
                    bits_per_value)*s)+reference_value)*scals[lup];
            val[i++] =  (double) ((grib_decode_unsigned_long(lres, &lpos,
                    bits_per_value)*s)+reference_value)*scals[lup];
            lup++;
        }
#endif

        maxv--;
        hcount=0;
        mmax++;
    }

    Assert(*len >= i);
    *len = i;

    if(d != 1) {
        for(i=0;i<*len;i++)
            val[i++] *= d;
    }

    grib_context_free(a->parent->h->context,scals);

    return ret;
}
static int  unpack_double(grib_accessor* a, double* val, size_t *len)
{
  grib_accessor_data_sh_unpacked* self =  (grib_accessor_data_sh_unpacked*)a;

  size_t i = 0;
  int ret = GRIB_SUCCESS;
  long   hcount = 0;
  long   lcount = 0;
  long   hpos = 0;
  long   lup = 0;
  long   mmax = 0;
  long   n_vals = 0;
  double *scals  = NULL;
  /* double *pscals=NULL; */
  double dummy=0;

  double s = 0;
  double d = 0;
  double laplacianOperator = 0;
  unsigned char* buf = NULL;
  unsigned char* hres = NULL;
  unsigned char* lres = NULL;
  unsigned long packed_offset;
  long   lpos = 0;

  long   maxv = 0;
  long   GRIBEX_sh_bug_present =0;
  long ieee_floats  = 0;

  long   offsetdata           = 0;
  long   bits_per_value          = 0;
  double reference_value      = 0;
  long   binary_scale_factor         = 0;
  long   decimal_scale_factor = 0;


  long   sub_j= 0;
  long   sub_k= 0;
  long   sub_m= 0;
  long   pen_j= 0;
  long   pen_k= 0;
  long   pen_m= 0;

  double operat= 0;
  int err=0;

  decode_float_proc decode_float = NULL;

  n_vals = 0;
  err=grib_value_count(a,&n_vals);
  if (err) return err;

  if(*len < n_vals){
    *len = n_vals;
    return GRIB_ARRAY_TOO_SMALL;
  }

  if((ret = grib_get_long_internal(grib_handle_of_accessor(a),self->offsetdata,&offsetdata))
      != GRIB_SUCCESS)   return ret;

  if((ret = grib_get_long_internal(grib_handle_of_accessor(a),self->GRIBEX_sh_bug_present,&GRIBEX_sh_bug_present))
      != GRIB_SUCCESS)
    return ret;

  if((ret = grib_get_long_internal(grib_handle_of_accessor(a),self->ieee_floats,&ieee_floats)) != GRIB_SUCCESS)
    return ret;

  if((ret = grib_get_long_internal(grib_handle_of_accessor(a),self->sub_j,&sub_j)) != GRIB_SUCCESS)
    return ret;
  if((ret = grib_get_long_internal(grib_handle_of_accessor(a),self->sub_k,&sub_k)) != GRIB_SUCCESS)
    return ret;
  if((ret = grib_get_long_internal(grib_handle_of_accessor(a),self->sub_m,&sub_m)) != GRIB_SUCCESS)
    return ret;
  if((ret = grib_get_long_internal(grib_handle_of_accessor(a),self->pen_j,&pen_j)) != GRIB_SUCCESS)
    return ret;
  if((ret = grib_get_long_internal(grib_handle_of_accessor(a),self->pen_k,&pen_k)) != GRIB_SUCCESS)
    return ret;
  if((ret = grib_get_long_internal(grib_handle_of_accessor(a),self->pen_m,&pen_m)) != GRIB_SUCCESS)
    return ret;

  self->dirty=0;

  switch (ieee_floats) {
    case 0:
      decode_float=grib_long_to_ibm;
      break;
    case 1:
      decode_float=grib_long_to_ieee;
      break;
    case 2:
      decode_float=grib_long_to_ieee64;
      break;
    default:
      return GRIB_NOT_IMPLEMENTED;
  }
  
  Assert (sub_j == sub_k);
  Assert (sub_j == sub_m);
  Assert (pen_j == pen_k);
  Assert (pen_j == pen_m);

  buf = (unsigned char*)grib_handle_of_accessor(a)->buffer->data;

  maxv = pen_j+1;

  buf  += offsetdata;
  hres = buf;
  lres = buf;

  packed_offset = offsetdata +  4*(sub_k+1)*(sub_k+2);

  lpos = 8*(packed_offset-offsetdata);

  s = grib_power(binary_scale_factor,2);
  d = grib_power(-decimal_scale_factor,10) ;

  scals   = (double*)grib_context_malloc(a->context,maxv*sizeof(double));
  Assert(scals);
  if((ret = grib_get_double_internal(grib_handle_of_accessor(a),self->laplacianOperator,&laplacianOperator))
      != GRIB_SUCCESS)
    return ret;

  scals[0] = 0;
  for(i=1;i<maxv;i++){
    operat = pow(i*(i+1),laplacianOperator);
    if(operat !=  0)
      scals[i] = (1.0/operat);
    else{
      scals[i] = 0;
    }
  }


  i=0;

  while(maxv>0)
  {
    lup=mmax;
    if(sub_k>=0)
    {
      for(hcount=0;hcount<sub_k+1;hcount++)
      {
        val[i++] =  decode_float(grib_decode_unsigned_long(hres,&hpos,32))*d;
        val[i++] =  decode_float(grib_decode_unsigned_long(hres,&hpos,32))*d;

        if (GRIBEX_sh_bug_present && hcount==sub_k){
          /*  bug in ecmwf data, last row (K+1)is scaled but should not */
          val[i-2] *= scals[lup];
          val[i-1] *= scals[lup];
        }
        lup++;
      }
      sub_k--;
    }

    /* pscals=scals+lup; */
    for(lcount=hcount; lcount < maxv ; lcount++)
    {
      dummy =  (double) ((grib_decode_unsigned_long(lres, &lpos,
                   bits_per_value)*s)+reference_value);
      dummy =  (double) ((grib_decode_unsigned_long(lres, &lpos,
                   bits_per_value)*s)+reference_value);
      lup++;
    }

    maxv--;
    hcount=0;
    mmax++;
  }

  Assert(*len >= i);
  *len = n_vals;

  if(d != 1) {
    for(i=0;i<*len;i++)
      val[i++] *= d;
  }

  (void)dummy; /* suppress gcc warning */
  grib_context_free(a->context,scals);

  return ret;

}
static int  unpack_double(grib_accessor* a, double* val, size_t *len)
{
    grib_accessor_data_2order_packing* self =  (grib_accessor_data_2order_packing*)a;

    size_t i = 0;
    size_t j = 0;
    size_t n_vals = 0;
    int err=0;

    long     vcount = 0, bias = 0;
    double   reference_value;
    long     binary_scale_factor;
    long     bits_per_value, decimal_scale_factor;
    long     n1 = 0, n2 = 0, extraValues = 0, p1 = 0, p2 = 0;

    long     offsetsection = 0, snd_bitmap = 0, snd_ordr_wdiff = 0;

    long  matrix_values    =0;
    long  general_ext    =0;
    long  boustrophedonic =0;
    long  two_ordr_spd =0;
    long  plus1_spd  =0;

    long  nbits_per_width =0;
    long  nbits_per_group_size =0;
    long  octet_start_group =0;
    long  width_spd_sp_desc =0;
    grib_handle* gh = grib_handle_of_accessor(a);

    unsigned char* buf_size_of_groups = (unsigned char*)gh->buffer->data;
    unsigned char* buf_width_of_group = (unsigned char*)gh->buffer->data;
    unsigned char* bufrefs = (unsigned char*)gh->buffer->data;
    unsigned char* bufvals = (unsigned char*)gh->buffer->data;

    double s = 0;
    double d = 0;

    double max = 0;
    double min = 0;

    unsigned long*  sec_val    = NULL;
    long  ref_vals    = 0;
    short  n_sp_diff = 0;

    short f_size_of_group = 0;
    short f_width_of_group = 0;

    long bitp = 0;
    long pointer_of_group_size = 0;
    long pointer_of_group_width = 0;
    long refsp = 0;
    long nap = 0;
    long nn=0;
    unsigned char* bitmap=NULL;
    grib_accessor* abitmap=NULL;
    size_t bitmap_len=0;

    err=grib_value_count(a,&nn);
    n_vals=nn;

    if((err = grib_get_long_internal(gh,self->offsetsection,&offsetsection))
            != GRIB_SUCCESS) return err;
    if((err = grib_get_long_internal(gh,self->bits_per_value,&bits_per_value))
            != GRIB_SUCCESS) return err;
    if((err = grib_get_double_internal(gh,self->reference_value, &reference_value))
            != GRIB_SUCCESS)return err;
    if((err = grib_get_long_internal(gh,self->binary_scale_factor, &binary_scale_factor))
            != GRIB_SUCCESS)  return err;
    if((err = grib_get_long_internal(gh,self->decimal_scale_factor, &decimal_scale_factor))
            != GRIB_SUCCESS)  return err;
    if((err = grib_get_long_internal(gh,self->n1,&n1))  != GRIB_SUCCESS) return err;
    if((err = grib_get_long_internal(gh,self->n2, &n2)) != GRIB_SUCCESS) return err;
    if((err = grib_get_long_internal(gh,self->p1, &p1)) != GRIB_SUCCESS) return err;
    if((err = grib_get_long_internal(gh,self->extraValues, &extraValues)) != GRIB_SUCCESS) return err;

    p1=p1+65536*extraValues;

    if((err = grib_get_long_internal(gh,self->p2, &p2)) != GRIB_SUCCESS)  return err;
    if((err = grib_get_long_internal(gh,self->matrix_values, &matrix_values))
            != GRIB_SUCCESS)return err;
    if((err = grib_get_long_internal(gh,self->snd_bitmap, &snd_bitmap))
            != GRIB_SUCCESS)  return err;
    if((err = grib_get_long_internal(gh,self->snd_ordr_wdiff, &snd_ordr_wdiff))
            != GRIB_SUCCESS) return err;
    if((err = grib_get_long_internal(gh,self->general_ext, &general_ext))
            != GRIB_SUCCESS)  return err;
    if((err = grib_get_long_internal(gh,self->boustrophedonic, &boustrophedonic))
            != GRIB_SUCCESS)  return err;
    if((err = grib_get_long_internal(gh,self->two_ordr_spd, &two_ordr_spd))
            != GRIB_SUCCESS) return err;
    if((err = grib_get_long_internal(gh,self->plus1_spd, &plus1_spd))
            != GRIB_SUCCESS)  return err;
    if((err = grib_get_long_internal(gh,self->width_widths, &nbits_per_width))
            != GRIB_SUCCESS) return err;
    if((err = grib_get_long_internal(gh,self->width_lengths, &nbits_per_group_size))
            != GRIB_SUCCESS) return err;
    if((err = grib_get_long_internal(gh,self->octet_start_group, &octet_start_group))
            != GRIB_SUCCESS) return err;

    if((err = grib_get_long_internal(gh,self->width_spd_sp_desc, &width_spd_sp_desc))
            != GRIB_SUCCESS) width_spd_sp_desc=-1;

    if((err = grib_get_long_internal(gh,self->nap, &nap)) != GRIB_SUCCESS) return err;

    self->dirty=0;

    n_sp_diff = two_ordr_spd*2+plus1_spd;

    Assert(bits_per_value < (sizeof(unsigned long)*8)-1);

    if ((abitmap=grib_find_accessor(gh,self->bitmap))!=NULL) {
        bitmap_len=grib_byte_count(abitmap);
        bitmap=(unsigned char*)grib_context_malloc_clear(a->context,sizeof(char)*bitmap_len);
        err=grib_unpack_bytes(abitmap,bitmap,&bitmap_len);
        if (err) {grib_context_free(a->context,bitmap); return err;}
    }

    if(bits_per_value == 0)
        return GRIB_NOT_IMPLEMENTED;

    /* I have everything now start decoding       */
    /*
    fprintf(stdout,"\n****************************************\n");
    fprintf(stdout," bits_per_value = %ld\n", bits_per_value);
    fprintf(stdout," reference_value = %g\n", reference_value);
    fprintf(stdout," binary_scale_factor = %ld\n", binary_scale_factor);
    fprintf(stdout," decimal_scale_factor = %ld\n", decimal_scale_factor);
    fprintf(stdout," n1 = %ld\n", n1);
    fprintf(stdout," n2 = %ld\n", n2);
    fprintf(stdout," p1 = %ld\n", p1);
    fprintf(stdout," p2 = %ld\n", p2);
    fprintf(stdout," matrix_values = %ld\n", matrix_values);
    fprintf(stdout," snd_bitmap = %ld\n", snd_bitmap);
    fprintf(stdout," snd_ordr_wdiff = %ld\n", snd_ordr_wdiff);
    fprintf(stdout," general_ext = %ld\n", general_ext);
    fprintf(stdout," boustrophedonic = %ld\n", boustrophedonic);
    fprintf(stdout," two_ordr_spd = %ld \n", two_ordr_spd);

    fprintf(stdout," plus1_spd = %ld\n", plus1_spd);

    fprintf(stdout," n_sp_diff = %d\n", n_sp_diff);
    fprintf(stdout," width_widths = %ld\n", nbits_per_group_size);
    fprintf(stdout," width_lengths = %ld\n", nbits_per_width);
    fprintf(stdout," octet_start_group = %ld\n", octet_start_group);
    fprintf(stdout," width_spd_sp_desc = %ld\n", width_spd_sp_desc);

    fprintf(stdout," offsetsection = %ld\n", offsetsection);
    fprintf(stdout," offset w = %ld\n", octet_start_group + offsetsection);
    fprintf(stdout,"\n****************************************\n");
    */
    if(snd_bitmap || matrix_values)
        return GRIB_NOT_IMPLEMENTED;

    sec_val  = (unsigned long*)grib_context_malloc(a->context,(n_vals)*sizeof(unsigned long));

    buf_width_of_group  +=  a->offset;
    buf_size_of_groups +=  offsetsection+(octet_start_group-1); /* -1 because of documented starting at 1(and not 0)*/
    bufrefs +=  offsetsection+n1-1;                  /* -1 because of documented starting at 1(and not 0)*/

    pointer_of_group_size  = 0;
    pointer_of_group_width    = 0;
    refsp   = 0;

    for(i=0;i < n_sp_diff;i++)
        sec_val[i] =  grib_decode_unsigned_long(buf_width_of_group,  &pointer_of_group_width,  width_spd_sp_desc);


    bias   =  grib_decode_signed_longb(buf_width_of_group,  &pointer_of_group_width,  width_spd_sp_desc);

    bufvals += offsetsection+n2-1;
    bitp   =  0;
    vcount =  n_sp_diff;

    if(pointer_of_group_width%8)
        pointer_of_group_width = 8+(pointer_of_group_width-(pointer_of_group_width%8));
#if KEEP_OLD == 1
    if(sd == NULL){
        sd = grib_context_malloc_clear(a->context,sizeof(second_order_packed));
        sd->packed_byte_count      = 0;
        sd->nbits_per_group_size   = nbits_per_group_size;
        sd->nbits_per_widths       = nbits_per_width;
        sd->size_of_group_array    = p1;
        sd->array_of_group_size    = grib_context_malloc_clear(a->context,sizeof(unsigned long)*sd->size_of_group_array);
        sd->array_of_group_width   = grib_context_malloc_clear(a->context,sizeof(unsigned long)*sd->size_of_group_array);
        sd->array_of_group_refs    = grib_context_malloc_clear(a->context,sizeof( long)*sd->size_of_group_array);
    }
#endif
    for(i=0;i < p1;i++){
        f_width_of_group    = (short) grib_decode_unsigned_long(buf_width_of_group,  &pointer_of_group_width,     nbits_per_width);
        f_size_of_group     = (short) grib_decode_unsigned_long(buf_size_of_groups,  &pointer_of_group_size, nbits_per_group_size);
        ref_vals            =         grib_decode_unsigned_long(bufrefs,  &refsp,    bits_per_value);
#if KEEP_OLD == 1

        if(sd->packed_byte_count == 0){
            sd->array_of_group_width[i]  = f_width_of_group;
            sd->array_of_group_size[i]   = f_size_of_group;
            sd->array_of_group_refs[i]   = ref_vals;
        }
#endif
        for(j=0; j < f_size_of_group;j++){
            sec_val[vcount+j] = ref_vals + grib_decode_unsigned_long(bufvals,  &bitp, f_width_of_group);
        }
        vcount += f_size_of_group;
    }
#if KEEP_OLD == 1
    if(sd->packed_byte_count == 0) sd->packed_byte_count = (bitp+7)/8;
#endif

    Assert (n_vals == vcount);
    /*for(i=0;i < 10;i++)
    printf("readvalue [%d] %ld     %ld bias %ld <<\n", i,sec_val[i],binary_scale_factor,bias );*/

    if(snd_ordr_wdiff)
        de_spatial_difference(a->context,sec_val, n_vals, n_sp_diff, bias);

    if(boustrophedonic)
        reverse_rows(sec_val,n_vals,nap,bitmap,bitmap_len);

    s = grib_power(binary_scale_factor,2);
    d = grib_power(-decimal_scale_factor,10) ;

    for(i=0;i < n_vals;i++)
        val[i] = (double) ((((double)sec_val[i])*s)+reference_value)*d;

    max = val[0];
    min = max;
    for(i=0;i< n_vals;i++)
    {
        if ( val[i] > max )
            max = val[i];
        else if ( val[i] < min )
            min = val[i];
    }
    min *= d;
    max *= d;

    grib_context_free(a->context,sec_val);
    if (bitmap!=NULL) grib_context_free(a->context,bitmap);

    return err;
}
static int unpack_double(grib_accessor* a, double* values, size_t *len)
{
  grib_accessor_data_g1second_order_row_by_row_packing* self =  (grib_accessor_data_g1second_order_row_by_row_packing*)a;
  int ret=0;
  long numberOfGroups,numberOfSecondOrderPackedValues;
  long* groupWidths=0;
  long* firstOrderValues=0;
  long* X=0;
  long numberOfRows,numberOfColumns;
  long *numbersPerRow;
  long pos=0;
  long widthOfFirstOrderValues=0;
  long jPointsAreConsecutive;
  unsigned char* buf = (unsigned char*)a->parent->h->buffer->data;
  long k,i,j,n,Ni,Nj;
  double reference_value;
  long binary_scale_factor;
  long decimal_scale_factor;
  double s,d;
  size_t groupWidthsSize=0;
  int bitmapPresent=0;
  size_t plSize=0;
  long* pl=0;

  buf += grib_byte_offset(a);

  if((ret=grib_get_long_internal(a->parent->h,self->numberOfGroups,&numberOfGroups)) != GRIB_SUCCESS)
         return ret;

  if((ret=grib_get_long_internal(a->parent->h,self->jPointsAreConsecutive,&jPointsAreConsecutive)) != GRIB_SUCCESS)
         return ret;

  if (self->bitmap) bitmapPresent=1;
  ret=grib_get_size(a->parent->h,self->pl,&plSize);
  if (ret==GRIB_SUCCESS) {
	  pl=grib_context_malloc_clear(a->parent->h->context,sizeof(long)*plSize);
	  if((ret=grib_get_long_array(a->parent->h,self->pl,pl,&plSize)) != GRIB_SUCCESS)
         return ret;
  }

  if((ret=grib_get_long_internal(a->parent->h,self->Ni,&Ni)) != GRIB_SUCCESS)
         return ret;
  if((ret=grib_get_long_internal(a->parent->h,self->Nj,&Nj)) != GRIB_SUCCESS)
         return ret;
  if (jPointsAreConsecutive) {
  	numberOfRows=Ni;
	numberOfColumns=Nj;
  } else {
  	numberOfRows=Nj;
	numberOfColumns=Ni;
  }

  numbersPerRow=grib_context_malloc_clear(a->parent->h->context,sizeof(long)*numberOfRows);
  if (bitmapPresent) {
	long *bitmap,*pbitmap;
	size_t numberOfPoints=Ni*Nj;

  	if (plSize) {
		numberOfPoints=0;
		for (i=0;i<numberOfRows;i++) numberOfPoints+=pl[i];
	} 
	bitmap=grib_context_malloc_clear(a->parent->h->context,sizeof(long)*numberOfPoints);
	pbitmap=bitmap;
	grib_get_long_array(a->parent->h,self->bitmap,bitmap,&numberOfPoints);
  	if (plSize) {
		for (i=0;i<numberOfRows;i++) {
			for (j=0;j<pl[i];j++) {
				numbersPerRow[i]+=*(bitmap++);
			}
		}
	} else {
		for (i=0;i<numberOfRows;i++) {
			numbersPerRow[i]=0;
			for (j=0;j<Ni;j++) {
				numbersPerRow[i]+=*(bitmap++);
			}
		}
	}

	grib_context_free(a->parent->h->context,pbitmap);
  } else {
  	if (plSize) {
		for (i=0;i<numberOfRows;i++) numbersPerRow[i]=pl[i];
	} else {
		for (i=0;i<numberOfRows;i++) 
			numbersPerRow[i]=numberOfColumns;
	}
  }

  if((ret=grib_get_long_internal(a->parent->h,self->widthOfFirstOrderValues,&widthOfFirstOrderValues)) != GRIB_SUCCESS)
         return ret;

  if((ret=grib_get_long_internal(a->parent->h,self->binary_scale_factor,&binary_scale_factor)) != GRIB_SUCCESS)
         return ret;

  if((ret=grib_get_long_internal(a->parent->h,self->decimal_scale_factor,&decimal_scale_factor)) != GRIB_SUCCESS)
         return ret;

  if((ret=grib_get_double_internal(a->parent->h,self->reference_value,&reference_value)) != GRIB_SUCCESS)
         return ret;

  if((ret=grib_get_long_internal(a->parent->h,self->numberOfSecondOrderPackedValues,
  					&numberOfSecondOrderPackedValues)) != GRIB_SUCCESS)
         return ret;

  groupWidths=grib_context_malloc_clear(a->parent->h->context,sizeof(long)*numberOfGroups);
  groupWidthsSize=numberOfGroups;
  if((ret=grib_get_long_array_internal(a->parent->h,self->groupWidths, groupWidths,&groupWidthsSize)) != GRIB_SUCCESS)
         return ret;

	firstOrderValues=grib_context_malloc_clear(a->parent->h->context,sizeof(long)*numberOfGroups);
	grib_decode_long_array(buf,&pos,widthOfFirstOrderValues,numberOfGroups,firstOrderValues);
	pos = 8 * ( (pos + 7 ) / 8);

	X=grib_context_malloc_clear(a->parent->h->context,sizeof(long)*numberOfSecondOrderPackedValues);
	n=0;
	k=0;
	for (i=0; i<numberOfGroups; i++) {
		if (groupWidths[i]>0) {
				for (j=0;j<numbersPerRow[k];j++) {
					X[n]=grib_decode_unsigned_long(buf,&pos,groupWidths[i]);
					X[n]+=firstOrderValues[i];
					n++;
				}
		} else {
				for (j=0;j<numbersPerRow[k];j++) {
					X[n]=firstOrderValues[i];
					n++;
				}
		}
		k++;
	}

	s = grib_power(binary_scale_factor,2);
	d = grib_power(-decimal_scale_factor,10) ;
	for (i=0; i<n; i++) {
		values[i] = (double) (((X[i]*s)+reference_value)*d);
	}
	grib_context_free(a->parent->h->context,firstOrderValues);
	grib_context_free(a->parent->h->context,X);
	grib_context_free(a->parent->h->context,groupWidths);
	if (plSize) grib_context_free(a->parent->h->context,pl);
  
  return ret;
}