Example #1
0
static int  unpack_long(grib_accessor* a, long* val, size_t *len)
{
  int ret=GRIB_SUCCESS;
  size_t size=0;
  size_t i;
  double max,min,d,b;
  double *values=0;
  long binaryScaleFactor,decimalScaleFactor;

  grib_accessor_second_order_bits_per_value* self = (grib_accessor_second_order_bits_per_value*)a;
  if (self->bitsPerValue) {
	*val=self->bitsPerValue;
  	return GRIB_SUCCESS;
  }

  if((ret = grib_get_size(a->parent->h, self->values,&size)) != GRIB_SUCCESS) {
	*val=self->bitsPerValue;
    return GRIB_SUCCESS;
  }

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

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

  values=grib_context_malloc_clear(a->parent->h->context,sizeof(double)*size);
  if (!values) {
  	grib_context_log(a->parent->h->context,GRIB_LOG_FATAL,"%s unable to allocate %ld bytes",
		a->name,(long)size);
	return GRIB_OUT_OF_MEMORY;
  }
  if((ret = grib_get_double_array_internal(a->parent->h, self->values,values,&size)) != GRIB_SUCCESS)
    return ret;

  max=values[0];
  min=max;
  for (i=1;i<size;i++) {
  	if (max<values[i]) max=values[i];
	if (min>values[i]) min=values[i];
  }

  d=grib_power(-decimalScaleFactor,10);
  b=grib_power(-binaryScaleFactor,2);

  /* self->bitsPerValue=(long)ceil(log((double)((max-min)*d+1))/log(2.0))-binaryScaleFactor; */
  self->bitsPerValue=number_of_bits((unsigned long)(fabs(max-min)*b*d));
  *val=self->bitsPerValue;

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

  return ret;
}
Example #2
0
long grib_get_decimal_scale_fact(double max, double min, long bpval,long binary_scale)
{
  double range         = max - min;
  double  zs           = 1;
  long          scale  = 0;
  const long last = 127; /* Depends on edition, should be parameter */

  unsigned long maxint = grib_power(bpval,2) - 1;
  double dmaxint=(double)maxint;

  range*=grib_power(-binary_scale,2);

  Assert (bpval >= 1);
  if(range == 0)
    return 0;

  while( (range * zs ) > dmaxint) {
    scale--;
    zs /= 10;
  }
  while( (range * zs)  <= dmaxint) {
    scale++;
    zs *= 10;
  }

  while( (unsigned long)(range * zs + 0.5) > maxint) {
    scale--;
    zs /= 10;
  }
  while( (unsigned long)(range * zs + 0.5)  <= maxint) {
    scale++;
    zs *= 10;
  }

    /* printf("grib_api: decimal_scale_fact=%ld max=%g min=%g bits_per_value=%ld binary_scale=%ld\n",scale,max,min,bpval,binary_scale); */

  Assert(scale >= -last && scale <= last);

  return scale;
}
Example #3
0
long grib_get_binary_scale_fact(double max, double min, long bpval,int *ret)
{

  double range         = max - min;
  double  zs           = 1;
  long          scale  = 0;
  const long last = 127; /* Depends on edition, should be parameter */

  unsigned long maxint = grib_power(bpval,2) - 1;
  double dmaxint=(double)maxint;
  
  *ret=0;

  Assert (bpval >= 1);
/*
  printf("---- Maxint %ld range=%g\n",maxint,range);
*/
  if(range == 0)
    return 0;

  /* range -= 1e-10; */
  while( (range * zs)  <= dmaxint) {
    scale--;
    zs *= 2;
  }

  while( (range * zs ) > dmaxint) {
    scale++;
    zs /= 2;
  }

  while( (unsigned long)(range * zs + 0.5)  <= maxint) {
    scale--;
    zs *= 2;
  }

  while( (unsigned long)(range * zs + 0.5) > maxint) {
    scale++;
    zs /= 2;
  }

  if (scale < -last) {
	  *ret=GRIB_UNDERFLOW;
	  /*printf("grib_get_binary_scale_fact: max=%g min=%g\n",max,min);*/
	  scale = -last;
  }
  Assert(scale <= last);

  return scale;

}
static int    unpack_double   (grib_accessor* a, double* val, size_t *len) {
    grib_accessor_simple_packing_error* self = (grib_accessor_simple_packing_error*)a;
    int ret = 0;
    long binaryScaleFactor=0;
    long bitsPerValue=0;
    long decimalScaleFactor=0;
    double referenceValue=0;

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

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

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

    if (!strcmp(self->floatType,"ibm"))
        *val=grib_ibmfloat_error(referenceValue);
    else if  (!strcmp(self->floatType,"ieee"))
        *val=grib_ieeefloat_error(referenceValue);
    else Assert(1==0);

    if (bitsPerValue!=0)
        *val=(*val+grib_power(binaryScaleFactor,2))*grib_power(-decimalScaleFactor,10)*0.5;

    if (ret == GRIB_SUCCESS) *len = 1;

    return ret;
}
Example #5
0
long grib_get_bits_per_value(double max, double min, long binary_scale_factor)
{

  double range         = max - min;
  double  zs           = 1;
  long          scale  = 0;
  const long last = 127; /* Depends on edition, should be parameter */

  unsigned long maxint = grib_power(binary_scale_factor,2) - 1;
  double dmaxint=(double)maxint;

  if (maxint==0) maxint=1;

/*
  printf("---- Maxint %ld range=%g\n",maxint,range);
*/
  if(range == 0)
    return 0;

  /* range -= 1e-10; */
  while( (range * zs)  <= dmaxint) { scale--;zs *= 2;}

  while( (range * zs ) > dmaxint) {scale++;zs /= 2;}

  while( (unsigned long)(range * zs + 0.5)  <= maxint) {
    scale--;
    zs *= 2;
  }

  while( (unsigned long)(range * zs + 0.5) > maxint) {
    scale++;
    zs /= 2;
  }

  Assert(scale >= -last && scale <= last);
 /* printf("---- scale=%ld\n",scale);*/

  return scale;

}
Example #6
0
long grib_op_pow(long a, long b) {return grib_power(a,b);}
static int unpack_double(grib_accessor* a, double* values, size_t *len)
{
  grib_accessor_data_g1second_order_constant_width_packing* self =  (grib_accessor_data_g1second_order_constant_width_packing*)a;
  int ret=0;
  long numberOfGroups,numberOfSecondOrderPackedValues;
  long groupWidth=0;
  long* firstOrderValues=0;
  long* X=0;
  long numberPerRow=0;
  long pos=0;
  long widthOfFirstOrderValues=0;
  long jPointsAreConsecutive;
  unsigned char* buf = (unsigned char*)grib_handle_of_accessor(a)->buffer->data;
  long i,n;
  double reference_value;
  long binary_scale_factor;
  long decimal_scale_factor;
  double s,d;
  long* secondaryBitmap;

  buf += grib_byte_offset(a);

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

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

	if (jPointsAreConsecutive) {
	  if((ret=grib_get_long_internal(grib_handle_of_accessor(a),self->Ni,&numberPerRow)) != GRIB_SUCCESS)
         return ret;
	} else {
	  if((ret=grib_get_long_internal(grib_handle_of_accessor(a),self->Nj,&numberPerRow)) != GRIB_SUCCESS)
         return ret;
	}

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

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

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

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

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

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

	secondaryBitmap=(long*)grib_context_malloc_clear(a->context,sizeof(long)*numberOfSecondOrderPackedValues);
	grib_decode_long_array(buf,&pos,1,numberOfSecondOrderPackedValues,secondaryBitmap);
	pos = 8 * ( (pos + 7 ) / 8);

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

	X=(long*)grib_context_malloc_clear(a->context,sizeof(long)*numberOfSecondOrderPackedValues);

	if (groupWidth>0) {
		grib_decode_long_array(buf,&pos,groupWidth,numberOfSecondOrderPackedValues,X);
		n=0;
		i=-1;
		while (n<numberOfSecondOrderPackedValues) {
			i+=secondaryBitmap[n];
			X[n]=firstOrderValues[i]+X[n];
			n++;
		}
	} else {
		n=0;
		i=-1;
		while (n<numberOfSecondOrderPackedValues) {
			i+=secondaryBitmap[n];
			X[n]=firstOrderValues[i];
			n++;
		}
	}


	/*
	{
	long extrabits = 16 * ( (pos + 15 ) / 16) - pos;
	printf("XXXXXXX extrabits=%ld pos=%ld\n",extrabits,pos);
	}
	*/

	s = grib_power(binary_scale_factor,2);
	d = grib_power(-decimal_scale_factor,10) ;
	for (i=0; i<numberOfSecondOrderPackedValues; i++) {
		values[i] = (double) (((X[i]*s)+reference_value)*d);
	}

	*len=numberOfSecondOrderPackedValues;
	grib_context_free(a->context,secondaryBitmap);
	grib_context_free(a->context,firstOrderValues);
	grib_context_free(a->context,X);
  
  return ret;
}
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;
}
static int pack_double(grib_accessor* a, const double* val, size_t *len)
{
    grib_accessor_data_2order_packing* self =  (grib_accessor_data_2order_packing*)a;
    grib_handle* gh = grib_handle_of_accessor(a);

    size_t i = 0;
    size_t j = 0;
    size_t n_vals = *len;
    size_t buff_len = 0;
    double divisor = 1;
    long     vcount = 0;
    int      err = 0;
    long     bias = 0;
    double   reference_value;
    long     binary_scale_factor;
    long     bits_per_value;
    /*long     bit_per_val_rectified_for_gribex;*/
    long     decimal_scale_factor;
    long     n1 = 0;
    long     n2 = 0;
    long     p1 = 0;
    long    n_unused_bits = 0;
    long   used_bits = 0;
    long   offsetsection  = 0;
    long   snd_bitmap     = 0;
    long   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   octet_start_group = 0;
    long   width_spd_sp_desc = 0;

    unsigned char* buf        = NULL;
    unsigned char* buf_size_of_groups   = NULL;
    unsigned char* buf_width_of_group = NULL;
    unsigned char* buf_refs   = NULL;
    unsigned char* buf_vals   = NULL;

    double d = 0;

    unsigned long*  sec_val    = NULL;
    unsigned long*  group_val  = NULL;

    short  n_sp_diff = 0;
    unsigned char* bitmap=NULL;
    grib_accessor* abitmap=NULL;
    size_t bitmap_len=0;

#if KEEP_OLD == 1

#else
    second_order_packed* sd = NULL;
#endif

    long   bitp = 0;
    long   pointer_of_group_size = 0;
    long   pointer_of_group_width = 0;
    long   refsp = 0;
    long   nap = 0;
    long offsetdata = 0;

    double max;
    double min;
    int extraValues=0;

    size_t nv =0;

    if (*len ==0) return GRIB_NO_VALUES;

    if((err = grib_get_long_internal(gh,self->offsetsection,&offsetsection)) != GRIB_SUCCESS) return err;
    if((err = grib_get_long_internal(gh,self->offsetdata,&offsetdata)) != 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_long_internal(gh,self->decimal_scale_factor, &decimal_scale_factor))  != 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->width_spd_sp_desc, &width_spd_sp_desc)) != GRIB_SUCCESS) return err;
    if((err = grib_get_long_internal(gh,self->nap, &nap)) != GRIB_SUCCESS) return err;

    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;}
    }

    two_ordr_spd = 1;
    plus1_spd = 0;

    if(bits_per_value == 0)
        return GRIB_NOT_IMPLEMENTED;

    n_sp_diff = two_ordr_spd*2+plus1_spd;
    /*     calculation of integer array   */

    sec_val  = (unsigned long*)grib_context_malloc(a->context,(n_vals)*sizeof(long));
    d = grib_power(decimal_scale_factor,10) ;
    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;

    /*bit_per_val_rectified_for_gribex = bits_per_value+8-bits_per_value%8;*/
    if (grib_get_nearest_smaller_value(gh,self->reference_value,min,&reference_value)
            !=GRIB_SUCCESS) {
        grib_context_log(a->context,GRIB_LOG_ERROR,
                "unable to find nearest_smaller_value of %g for %s",min,self->reference_value);
        return GRIB_INTERNAL_ERROR;
    }

    /*  the scale factor in Grib 1 is adjusted in gribex, for "normalization purpose" ... ?*/
    binary_scale_factor    = grib_get_binary_scale_fact(max,reference_value,bits_per_value,&err);

    divisor         = grib_power(-binary_scale_factor,2);


    for(i=0;i< n_vals;i++)
        sec_val[i] = (unsigned long)((((val[i]*d)-reference_value)*divisor)+0.5);

    /*  reverse the rows*/
    if(boustrophedonic)
        reverse_rows(sec_val,n_vals,nap,bitmap,bitmap_len);


    if(snd_ordr_wdiff)
        if((err =  spatial_difference(a->context,sec_val, n_vals, n_sp_diff, &bias))){
            grib_context_free(a->context,sec_val);
            return err;
        }



    /*   for(i=0;i < 10;i++)
      printf("packing value [%d] %g %ld     %ld bias %ld <<\n", i, val[i],sec_val[i],binary_scale_factor,bias );
     */
    nv        = n_vals-n_sp_diff;
    group_val = sec_val+n_sp_diff;

#if KEEP_OLD == 1

#else
    sd = grib_get_second_order_groups(a->context, group_val, nv);
#endif

    bitp   = 0;
    p1     = sd->size_of_group_array;

    bitp                         =   (width_spd_sp_desc*(n_sp_diff+1)) ;
    octet_start_group            =   (bitp+7)/8;

    bitp                         =   (p1*sd->nbits_per_widths);
    octet_start_group           +=   (bitp+7)/8;

    bitp                         =   (octet_start_group*8) + (sd->nbits_per_group_size*p1);
    n1                           =   (bitp+7)/8;

    bitp                         =   n1*8 + bits_per_value*p1;
    n2                           =   (bitp+7)/8;

    used_bits = n2*8;

    buff_len     = (n2+sd->packed_byte_count);

    if((a->offset+buff_len)%2) buff_len++;

    buf = NULL;
    buf = (unsigned char*)grib_context_malloc_clear(a->context,buff_len);

    buf_width_of_group    =  buf;
    buf_size_of_groups    =  buf+octet_start_group;
    buf_refs    =  buf+n1;
    buf_vals    =  buf+n2;

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

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

    grib_encode_signed_longb(buf_width_of_group, bias, &pointer_of_group_width,  width_spd_sp_desc);

    if(pointer_of_group_width%8)
        pointer_of_group_width = 8+(pointer_of_group_width-(pointer_of_group_width%8));

    vcount    = n_sp_diff;

    for(i = 0;i<p1;i++){
        grib_encode_unsigned_longb(buf_width_of_group,sd->array_of_group_width[i],&pointer_of_group_width,sd->nbits_per_widths);
        grib_encode_unsigned_longb(buf_size_of_groups,sd->array_of_group_size[i], &pointer_of_group_size ,sd->nbits_per_group_size);
        grib_encode_unsigned_longb(buf_refs,  sd->array_of_group_refs[i],  &refsp  , bits_per_value);
        used_bits += sd->array_of_group_size[i]*sd->array_of_group_width[i];
        for(j=0; j < sd->array_of_group_size[i];j++){
            grib_encode_unsigned_longb(buf_vals, sec_val[vcount+j]-sd->array_of_group_refs[i] ,&bitp , sd->array_of_group_width[i]);

            /*    if(vcount+j < 10)
             printf(">>packing value [%ld] %g %ld     %ld nb %ld <<\n", vcount+j, val[vcount+j],sec_val[vcount+j],binary_scale_factor,sd->array_of_group_refs[i] );*/
        }
        vcount+= sd->array_of_group_size[i];
    }
    n_unused_bits = (buff_len*8)-used_bits;

    grib_buffer_replace(a, buf,buff_len,1,1);

    if((buff_len + (offsetdata-offsetsection)) %2) {
        buff_len ++;
        grib_update_size(a,buff_len);
    }

    octet_start_group += 1+ a->offset-offsetsection;
    if((err = grib_set_long_internal(gh,self->octet_start_group, octet_start_group)) != GRIB_SUCCESS) return err;

    n1 += 1+a->offset-offsetsection;
    if((err = grib_set_long_internal(gh,self->n1,n1)) != GRIB_SUCCESS) return err;

    n2 += 1+a->offset-offsetsection;
    if((err = grib_set_long_internal(gh,self->n2,n2)) != GRIB_SUCCESS) return err;

    extraValues=0;
    while (p1 > 65535) {
        p1-=65536;
        extraValues++;
    }

    if((err = grib_set_long_internal(gh,self->p1,p1)) != GRIB_SUCCESS) return err;

    if((err = grib_set_long_internal(gh,self->extraValues,extraValues)) != GRIB_SUCCESS) return err;

    if((err = grib_set_long_internal(gh,self->p2,n_vals - n_sp_diff)) != GRIB_SUCCESS) return err;

    if((err = grib_set_double_internal(gh,self->reference_value,    reference_value)) != GRIB_SUCCESS)return err;

    {
        /* Make sure we can decode it again */
        double ref = 1e-100;
        grib_get_double_internal(gh,self->reference_value,&ref);
        Assert(ref == reference_value);
    }

    if((err = grib_set_long_internal(gh,self->binary_scale_factor,         binary_scale_factor)) != GRIB_SUCCESS)  return err;

    if((err = grib_set_long_internal(gh,self->decimal_scale_factor, decimal_scale_factor))  != GRIB_SUCCESS)  return err;
    if((err = grib_set_long_internal(gh,self->width_widths,  sd->nbits_per_widths)) != GRIB_SUCCESS) return err;
    if((err = grib_set_long_internal(gh,self->width_lengths, sd->nbits_per_group_size)) != GRIB_SUCCESS) return err;


    err = grib_set_long_internal(gh,self->half_byte, n_unused_bits);
    if(err != GRIB_SUCCESS) return err;

#if KEEP_OLD == 1

#else

    grib_free_second_order_groups(a->context,sd);
#endif
    ;

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

    return GRIB_SUCCESS;
}
static int pack_double(grib_accessor* a, const 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 s = 0;
    double d = 0;

    unsigned char* buf    = NULL;

    size_t         buflen = 0;
    size_t         hsize = 0;
    size_t         lsize = 0;

    unsigned char* hres = NULL;
    unsigned char* lres = NULL;

    long   lpos = 0;
    long   maxv = 0;

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

    double laplacianOperator = 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;
    long   GRIBEX_sh_bug_present =0;
    long   ieee_floats =0;
    double min = 0;
    double max = 0;
    double current_val = 0;
    short mixmax_unset = 0;
    int bytes;

    encode_float_proc encode_float = NULL;

    if (*len ==0) return GRIB_NO_VALUES;

    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_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_long_internal(a->parent->h,self->laplacianOperatorIsSet,&laplacianOperatorIsSet)) != 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=1;


    switch (ieee_floats) {
    case 0:
        encode_float =grib_ibm_to_long;
        bytes=4;
        break;
    case 1:
        encode_float =grib_ieee_to_long;
        bytes=4;
        break;
    case 2:
        encode_float =grib_ieee64_to_long;
        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);

    n_vals = (pen_j+1)*(pen_j+2);
    d = grib_power(decimal_scale_factor,10) ;

    if(*len != n_vals){
        grib_context_log(a->parent->h->context,GRIB_LOG_ERROR,"COMPLEX_PACKING : wrong number of values, expected %d - got %d",n_vals,*len);
        return GRIB_INTERNAL_ERROR;
    }

    if (pen_j == sub_j) {
        double* values;
        if (d) {
            values=(double*)grib_context_malloc_clear(a->parent->h->context,sizeof(double)*n_vals);
            for (i=0;i<n_vals;i++) values[i]=val[i]*d;
        } else {
            values=(double*)val;
        }
        buflen=n_vals*bytes;
        buf = (unsigned char*)grib_context_malloc_clear(a->parent->h->context,buflen);
        grib_ieee_encode_array(a->parent->h->context,values,n_vals,bytes,buf);
        if (d) grib_context_free(a->parent->h->context,values);
        grib_buffer_replace(a, buf, buflen,1,1);
        grib_context_free(a->parent->h->context,buf);
        return 0;
    }

    if(!laplacianOperatorIsSet) {
        laplacianOperator = calculate_pfactor(a->parent->h->context,val,pen_j,sub_j);
        if((ret = grib_set_double_internal(a->parent->h,self->laplacianOperator,laplacianOperator))
                != GRIB_SUCCESS) return ret;
        grib_get_double_internal(a->parent->h,self->laplacianOperator,&laplacianOperator);
    }

    /*
     printf("PACKING LAPLACE set=%ld value=%.20f\n",laplacianOperatorIsSet,laplacianOperator);
    */

    hsize = 4*(sub_k+1)*(sub_k+2);
    lsize = ((n_vals - ((sub_k+1)*(sub_k+2)))*bits_per_value)/8;

    buflen = hsize+lsize;

    buf  = (unsigned char*)grib_context_malloc(a->parent->h->context,buflen);
    hres = buf;
    lres = buf+hsize;

    maxv = pen_j+1;

    lpos = 0;
    hpos = 0;

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

    scals[0] =0;
    for(i=1;i<maxv;i++)
        scals[i] = ((double)pow(i*(i+1),laplacianOperator));


    i=0;

    mmax = 0;
    maxv = pen_j+1;
    i=0;
    lcount=0;
    hcount=0;
    sub_k = sub_j;

    while(maxv>0)
    {
        lup=mmax;

        if(sub_k>=0)
        {
            i   += 2*(sub_k+1);
            lup +=    sub_k+1 ;
            hcount += sub_k+1 ;
            sub_k--;
        }

        for(lcount=hcount; lcount < maxv ; lcount++)
        {
            current_val = ((val[i++]*d) * scals[lup]);
            if(mixmax_unset == 0){
                max = current_val;
                min = current_val;
                mixmax_unset = 1;
            }

            if(current_val > max) max = current_val;
            if(current_val < min) min = current_val;

            current_val = ((val[i++]*d) * scals[lup]);
            if(current_val > max) max = current_val;
            if(current_val < min) min = current_val;

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

    if (grib_get_nearest_smaller_value(a->parent->h,self->reference_value,min,&reference_value)
            !=GRIB_SUCCESS) {
        grib_context_log(a->parent->h->context,GRIB_LOG_ERROR,
                "unable to find nearest_smaller_value of %g for %s",min,self->reference_value);
        exit(GRIB_INTERNAL_ERROR);
    }
    binary_scale_factor = grib_get_binary_scale_fact(max,reference_value,bits_per_value,&ret);

    if (ret==GRIB_UNDERFLOW) {
        d=0;
        binary_scale_factor = 0;
        reference_value=0;

    }
    s = grib_power(-binary_scale_factor,2);

    /* printf("D : %.30f\n",d); */

    i=0;

    mmax = 0;
    maxv = pen_j+1;
    i=0;
    lcount=0;
    hcount=0;
    sub_k = sub_j;

    while(maxv>0)
    {
        lup=mmax;

        if(sub_k>=0)
        {
            for(hcount=0;hcount<sub_k+1;hcount++)
            {
                if ( GRIBEX_sh_bug_present && hcount==sub_k ) {
                    /* _test(val[i]*d*scals[lup],1); */
                    grib_encode_unsigned_long(hres, encode_float((val[i++]*d)*scals[lup]) , &hpos, 32);
                    /* _test(val[i]*d*scals[lup],1); */
                    grib_encode_unsigned_long(hres, encode_float((val[i++]*d)*scals[lup]) , &hpos, 32);
                }else{

                    /* _test(val[i]*d,0); */

                    grib_encode_unsigned_long(hres, encode_float(val[i++]*d) , &hpos, 32);
                    /* _test(val[i]*d,0); */
                    grib_encode_unsigned_long(hres, encode_float(val[i++]*d) , &hpos, 32);
                }
                lup++;
            }
            sub_k--;
        }

#if FAST_BIG_ENDIAN
        grib_encode_double_array_complex((maxv-hcount)*2,&(val[i]),bits_per_value,reference_value,&(scals[lup]),d,s,lres,&lpos);
        i+=(maxv-hcount)*2;
#else
        if (bits_per_value % 8) {
            for(lcount=hcount; lcount < maxv ; lcount++)
            {
                current_val = (((((val[i++]*d) * scals[lup])-reference_value)*s)+0.5);
                if(current_val < 0)
                    grib_context_log(a->parent->h->context,GRIB_LOG_ERROR,
                            "COMPLEX_PACKING : negative coput before packing (%g)", current_val);
                grib_encode_unsigned_longb(lres, current_val, &lpos, bits_per_value);

                current_val = (((((val[i++]*d) * scals[lup])-reference_value)*s)+0.5);
                if(current_val < 0)
                    grib_context_log(a->parent->h->context,GRIB_LOG_ERROR,
                            "COMPLEX_PACKING : negative coput before packing (%g)", current_val);
                grib_encode_unsigned_longb(lres, current_val, &lpos, bits_per_value);
                lup++;
            }
        } else {
            for(lcount=hcount; lcount < maxv ; lcount++)
            {
                current_val = (((((val[i++]*d) * scals[lup])-reference_value)*s)+0.5);
                if(current_val < 0)
                    grib_context_log(a->parent->h->context,GRIB_LOG_ERROR,
                            "COMPLEX_PACKING : negative coput before packing (%g)", current_val);
                grib_encode_unsigned_long(lres, current_val, &lpos, bits_per_value);

                current_val = (((((val[i++]*d) * scals[lup])-reference_value)*s)+0.5);
                if(current_val < 0)
                    grib_context_log(a->parent->h->context,GRIB_LOG_ERROR,
                            "COMPLEX_PACKING : negative coput before packing (%g)", current_val);
                grib_encode_unsigned_long(lres, current_val, &lpos, bits_per_value);
                lup++;
            }
        }
#endif

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

    if(((hpos/8) != hsize) &&((lpos/8) != lsize))
    {
        grib_context_log(a->parent->h->context,GRIB_LOG_ERROR,
                "COMPLEX_PACKING : Mismatch in packing between high resolution and low resolution part");
        grib_context_free(a->parent->h->context,buf);
        grib_context_free(a->parent->h->context,scals);
        return GRIB_INTERNAL_ERROR;
    }

    buflen = ((hpos + lpos)/8);

    if((ret = grib_set_double_internal(a->parent->h,self->reference_value, reference_value)) != GRIB_SUCCESS)
        return ret;
    {
        /* Make sure we can decode it again */
        double ref = 1e-100;
        grib_get_double_internal(a->parent->h,self->reference_value,&ref);
        Assert(ref == reference_value);
    }

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

    grib_buffer_replace(a, buf, buflen,1,1);
    grib_context_free(a->parent->h->context,buf);
    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_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 pack_double(grib_accessor* a, const double* cval, size_t *len)
{
    grib_accessor_data_jpeg2000_packing *self =(grib_accessor_data_jpeg2000_packing*)a;
    grib_accessor_class* super = *(a->cclass->super);
    size_t n_vals = *len;
    int err = 0;
    int i;
    double reference_value = 0;
    long   binary_scale_factor = 0;
    long   bits_per_value = 0;
    long   decimal_scale_factor = 0;
    double decimal = 1;
    size_t simple_packing_size = 0;
    unsigned char*  buf = NULL;
    double divisor = 1;
    long width;
    long height;
    long ni;
    long nj;
    long target_compression_ratio;
    long type_of_compression_used;
    long scanning_mode;
    long list_defining_points;
    long number_of_data_points;
    int ret =0;
    j2k_encode_helper helper;
    double units_factor=1.0;
    double units_bias=0.0;
    double* val=(double*)cval;

    self->dirty=1;

    if(*len == 0){
        grib_buffer_replace(a, NULL, 0, 1, 1);
        return GRIB_SUCCESS;
    }

    if(self->units_factor &&
            (grib_get_double_internal(a->parent->h,self->units_factor,&units_factor)== GRIB_SUCCESS)) {
        grib_set_double_internal(a->parent->h,self->units_factor,1.0);
    }

    if(self->units_bias &&
            (grib_get_double_internal(a->parent->h,self->units_bias,&units_bias)== GRIB_SUCCESS)) {
        grib_set_double_internal(a->parent->h,self->units_bias,0.0);
    }

    if (units_factor != 1.0) {
        if (units_bias != 0.0)
            for (i=0;i<n_vals;i++) val[i]=val[i]*units_factor+units_bias;
        else
            for (i=0;i<n_vals;i++) val[i]*=units_factor;
    } else if (units_bias != 0.0)
        for (i=0;i<n_vals;i++) val[i]+=units_bias;

    ret = super->pack_double(a,val,len);
    switch (ret) {
    case GRIB_CONSTANT_FIELD:
        grib_buffer_replace(a, NULL, 0,1,1);
        return GRIB_SUCCESS;
        break;
    case GRIB_SUCCESS:
        break;
    default:
        grib_context_log(a->parent->h->context,GRIB_LOG_ERROR,"unable to compute packing parameters\n");
        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->bits_per_value,&bits_per_value)) !=
            GRIB_SUCCESS)
        return ret;

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

    decimal = grib_power(decimal_scale_factor,10) ;
    divisor = grib_power(-binary_scale_factor,2);

    simple_packing_size = (((bits_per_value*n_vals)+7)/8)*sizeof(unsigned char);
    buf  = (unsigned char*)grib_context_malloc_clear(a->parent->h->context,simple_packing_size+EXTRA_BUFFER_SIZE);
    if(!buf) {
        err = GRIB_OUT_OF_MEMORY;
        goto cleanup;
    }

    if((err = grib_get_long_internal(a->parent->h,self->ni,&ni)) != GRIB_SUCCESS)
        return err;
    if((err = grib_get_long_internal(a->parent->h,self->nj,&nj)) != GRIB_SUCCESS)
        return err;
    if((err = grib_get_long_internal(a->parent->h,self->type_of_compression_used,&type_of_compression_used)) != GRIB_SUCCESS)
        return err;
    if((err = grib_get_long_internal(a->parent->h,self->target_compression_ratio,&target_compression_ratio)) != GRIB_SUCCESS)
        return err;
    if((err = grib_get_long_internal(a->parent->h,self->scanning_mode,&scanning_mode)) != GRIB_SUCCESS)
        return err;
    if((err = grib_get_long_internal(a->parent->h,self->list_defining_points,&list_defining_points)) != GRIB_SUCCESS)
        return err;
    if((err = grib_get_long_internal(a->parent->h,self->number_of_data_points,&number_of_data_points)) != GRIB_SUCCESS)
        return err;

    width  = ni;
    height = nj;

    if((scanning_mode & (1<<5)) != 0)
    {
        long tmp = width;
        width    = height;
        height   = tmp;
    }

    /* The grid is not regular */
    if(list_defining_points != 0)
    {
        width  = *len;
        height = 1;
    }

    /* There is a bitmap */
    if(*len != number_of_data_points)
    {
        width  = *len;
        height = 1;
    }

    if(width*height != *len)
    {
        /* fprintf(stderr,"width=%ld height=%ld len=%d\n",(long)width,(long)height,(long)*len); */
        Assert(width*height == *len);
    }

    switch( type_of_compression_used)
    {
    case 0:
        Assert(target_compression_ratio == 255);
        helper.compression = 0;
        break;

    case 1:
        Assert(target_compression_ratio != 255);
        Assert(target_compression_ratio != 0);
        helper.compression = target_compression_ratio;
        break;

    default:
        err = GRIB_NOT_IMPLEMENTED;
        goto cleanup;
    }

    helper.jpeg_buffer     = buf;
    helper.width           = width;
    helper.height          = height;

    /* See GRIB-438 */
    if (bits_per_value == 0) {
        const long bits_per_value_adjusted = 1;
        grib_context_log(a->parent->h->context, GRIB_LOG_DEBUG,
                "grib_accessor_class_data_jpeg2000_packing(%s) : bits per value was zero, changed to %d",
                self->jpeg_lib==OPENJPEG_LIB ? "openjpeg" : "jasper", bits_per_value_adjusted);
        bits_per_value = bits_per_value_adjusted;
    }
    helper.bits_per_value  = bits_per_value;

    helper.buffer_size     = simple_packing_size + EXTRA_BUFFER_SIZE;
    helper.values          = val;
    helper.no_values       = n_vals;
    helper.reference_value = reference_value;
    helper.divisor         = divisor;
    helper.decimal         = decimal;
    helper.jpeg_length     = 0;

    switch (self->jpeg_lib) {
    case OPENJPEG_LIB:
        if ( (err = grib_openjpeg_encode(a->parent->h->context,&helper)) != GRIB_SUCCESS ) goto cleanup;
        break;
    case JASPER_LIB:
        if ( (err = grib_jasper_encode(a->parent->h->context,&helper)) != GRIB_SUCCESS ) goto cleanup;
        break;
    }

    if(helper.jpeg_length > simple_packing_size)
        grib_context_log(a->parent->h->context, GRIB_LOG_WARNING,
                "grib_accessor_data_jpeg2000_packing(%s) : jpeg data (%ld) larger than input data (%ld)",
                self->jpeg_lib==OPENJPEG_LIB ? "openjpeg" : "jasper",
                        helper.jpeg_length, simple_packing_size);

    Assert( helper.jpeg_length <= helper.buffer_size);

    if(self->dump_jpg) {
        FILE *f = fopen(self->dump_jpg,"w");
        if(f) {
            if(fwrite(helper.jpeg_buffer,helper.jpeg_length,1,f) != 1)
                perror(self->dump_jpg);
            if (fclose(f) != 0)
                perror(self->dump_jpg);
        }
        else perror(self->dump_jpg);
    }

    grib_buffer_replace(a, helper.jpeg_buffer, helper.jpeg_length, 1, 1);

    cleanup:

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

    if(err == GRIB_SUCCESS)
        err = grib_set_long_internal(a->parent->h,self->number_of_values, *len);
    return err;

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

    int err = GRIB_SUCCESS;
    int i;
    size_t buflen = grib_byte_count(a);

    double bscale = 0;
    double dscale = 0;
    unsigned char* buf = NULL;
    size_t n_vals = 0;
    long nn=0;

    long binary_scale_factor = 0;
    long decimal_scale_factor = 0;
    double reference_value = 0;
    long bits_per_value =0;
    double units_factor=1.0;
    double units_bias=0.0;

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

    if(self->units_factor)
        grib_get_double_internal(a->parent->h,self->units_factor,&units_factor);

    if(self->units_bias)
        grib_get_double_internal(a->parent->h,self->units_bias,&units_bias);


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

    self->dirty=0;

    bscale = grib_power(binary_scale_factor,2);
    dscale = grib_power(-decimal_scale_factor,10);

    /* TODO: This should be called upstream */
    if(*len < n_vals)
        return GRIB_ARRAY_TOO_SMALL;

    /* Special case */

    if(bits_per_value == 0)
    {
        for(i = 0; i < n_vals; i++)
            val[i] = reference_value;
        *len = n_vals;
        return GRIB_SUCCESS;
    }

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

    switch (self->jpeg_lib) {
    case OPENJPEG_LIB:
        if ((err = grib_openjpeg_decode(a->parent->h->context,buf,&buflen,val,&n_vals)) != GRIB_SUCCESS)
            return err;
        break;
    case JASPER_LIB:
        if ((err = grib_jasper_decode(a->parent->h->context,buf,&buflen,val,&n_vals)) != GRIB_SUCCESS)
            return err;
        break;
    }

    *len = n_vals;

    for (i = 0; i < n_vals; i++) {
        val[i] = (val[i] * bscale + reference_value) * dscale;
    }
    if (units_factor != 1.0) {
        if (units_bias != 0.0)
            for (i=0;i<n_vals;i++) val[i]=val[i]*units_factor+units_bias;
        else
            for (i=0;i<n_vals;i++) val[i]*=units_factor;
    } else if (units_bias != 0.0)
        for (i=0;i<n_vals;i++) val[i]+=units_bias;

    return err;
}
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 grib_codetable* load_table(grib_accessor_codetable* self)
{
  size_t size = 0;
  grib_handle*    h = ((grib_accessor*)self)->parent->h;
  grib_context*   c = h->context;
  grib_codetable* t = NULL;
  grib_codetable* next=NULL ;
  grib_accessor* a=(grib_accessor*)self;
  char *filename=0;
  char name[1024]={0,};
  char recomposed[1024]={0,};
  char localRecomposed[1024]={0,};
  char *localFilename=0;
  char localName[1024]={0,};
  char masterDir[1024]={0,};
  char localDir[1024]={0,};
  size_t len=1024;

  if (self->masterDir != NULL)
    grib_get_string(h,self->masterDir,masterDir,&len);

  len=1024;
  if (self->localDir != NULL)
    grib_get_string(h,self->localDir,localDir,&len);

  if (*masterDir!=0) {
    sprintf(name,"%s/%s",masterDir,self->tablename);
    grib_recompose_name(h, NULL,name, recomposed,0);
    filename=grib_context_full_path(c,recomposed);
  } else {
    grib_recompose_name(h, NULL,self->tablename, recomposed,0);
    filename=grib_context_full_path(c,recomposed);
  }

  if (*localDir!=0) {
    sprintf(localName,"%s/%s",localDir,self->tablename);
    grib_recompose_name(h, NULL,localName, localRecomposed,0);
    localFilename=grib_context_full_path(c,localRecomposed);
  }
  
  next=c->codetable;
  while(next) {
    if((filename && next->filename[0] && strcmp(filename,next->filename[0]) == 0) &&
       ((localFilename==0 && next->filename[1]==NULL) ||
           ((localFilename!=0 && next->filename[1]!=NULL)
           && strcmp(localFilename,next->filename[1]) ==0)) )
      return next;
    next = next->next;
  }

  if (a->flags & GRIB_ACCESSOR_FLAG_TRANSIENT) {
	  Assert(a->vvalue!=NULL);
    size=a->vvalue->length*8;
  } else {
    size = grib_byte_count((grib_accessor*)self) * 8;
  }
  size = grib_power(size,2);

  t = (grib_codetable*)grib_context_malloc_clear_persistent(c,sizeof(grib_codetable) +
      (size-1)*sizeof(code_table_entry));

  if (filename!=0) grib_load_codetable(c,filename,recomposed,size,t);

  if (localFilename!=0) grib_load_codetable(c,localFilename,localRecomposed,size,t);

  if (t->filename[0]==NULL && t->filename[1]==NULL) {
    grib_context_free_persistent(c,t);
    return NULL;
  }
  
  return t;

}
static int pack_double(grib_accessor* a, const double* cval, size_t *len)
{
    grib_accessor_data_g1simple_packing* self =  (grib_accessor_data_g1simple_packing*)a;
    grib_accessor_class* super = *(a->cclass->super);

    size_t n_vals = *len;
    long half_byte = 0;
    int ret = 0;
    long offsetdata = 0;
    long offsetsection = 0;
    double reference_value = 0;
    long   binary_scale_factor = 0;
    long   bits_per_value = 0;
    long   decimal_scale_factor = 0;
    double decimal = 1;
    size_t buflen = 0;
    unsigned char*  buf = NULL;
    unsigned char*  encoded = NULL;
    double divisor = 1;
    int i;
    long off = 0;
    grib_context* c=a->parent->h->context;
    grib_handle* h=a->parent->h;
    char* ieee_packing_s=NULL;
    char* packingType_s=NULL;
    char* precision_s=NULL;
    double units_factor=1.0;
    double units_bias=0.0;
    double* val=(double*)cval;
    double missingValue=9999.0;
    long constantFieldHalfByte=0;
    int err=0;

    if(*len != 0) {
        if(self->units_factor &&
                (grib_get_double_internal(a->parent->h,self->units_factor,&units_factor)== GRIB_SUCCESS)) {
            grib_set_double_internal(a->parent->h,self->units_factor,1.0);
        }

        if(self->units_bias &&
                (grib_get_double_internal(a->parent->h,self->units_bias,&units_bias)== GRIB_SUCCESS)) {
            grib_set_double_internal(a->parent->h,self->units_bias,0.0);
        }

        if (units_factor != 1.0) {
            if (units_bias != 0.0)
                for (i=0;i<n_vals;i++) val[i]=val[i]*units_factor+units_bias;
            else
                for (i=0;i<n_vals;i++) val[i]*=units_factor;
        } else if (units_bias != 0.0)
            for (i=0;i<n_vals;i++) val[i]+=units_bias;

        if (c->ieee_packing && self->ieee_packing) {
            long precision=c->ieee_packing==32 ? 1 : 2;
            size_t lenstr=strlen(self->ieee_packing);

            packingType_s=grib_context_strdup(c,self->packingType);
            ieee_packing_s=grib_context_strdup(c,self->ieee_packing);
            precision_s=grib_context_strdup(c,self->precision);

            grib_set_string(h,packingType_s,ieee_packing_s,&lenstr);
            grib_set_long(h,precision_s,precision);

            grib_context_free(c,packingType_s);
            grib_context_free(c,ieee_packing_s);
            grib_context_free(c,precision_s);
            return grib_set_double_array(h,"values",val,*len);
        }
    }

    ret = super->pack_double(a,val,len);
    switch (ret) {
    case GRIB_CONSTANT_FIELD:
        ret=grib_get_long(a->parent->h,"constantFieldHalfByte",&constantFieldHalfByte);
        if (ret) constantFieldHalfByte=0;
        if((ret = grib_set_long_internal(a->parent->h,self->half_byte, constantFieldHalfByte))
                != GRIB_SUCCESS)
            return ret;
        grib_buffer_replace(a, NULL, 0,1,1);
        return GRIB_SUCCESS;
        break;
    case GRIB_NO_VALUES:
        ret=grib_get_long(a->parent->h,"constantFieldHalfByte",&constantFieldHalfByte);
        if (ret) constantFieldHalfByte=0;
        /* TODO move to def file */
        grib_get_double(a->parent->h,"missingValue", &missingValue);
        if((err = grib_set_double_internal(a->parent->h,self->reference_value, missingValue)) !=
                GRIB_SUCCESS)
            return err;
        if((ret = grib_set_long_internal(a->parent->h,self->binary_scale_factor, binary_scale_factor))
                != GRIB_SUCCESS)
            return ret;
        if((ret = grib_set_long_internal(a->parent->h,self->half_byte, constantFieldHalfByte))
                != GRIB_SUCCESS)
            return ret;
        grib_buffer_replace(a, NULL, 0,1,1);
        return GRIB_SUCCESS;
        break;
    case GRIB_INVALID_BPV:
        grib_context_log(a->parent->h->context,GRIB_LOG_ERROR,"unable to compute packing parameters\n");
        return ret;
    case GRIB_SUCCESS:
        break;
    default:
        grib_context_log(a->parent->h->context,GRIB_LOG_FATAL,"unable to compute packing parameters\n");
        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->bits_per_value,&bits_per_value)) !=
            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->offsetdata,&offsetdata)) != GRIB_SUCCESS)
        return ret;

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

    decimal = grib_power(decimal_scale_factor,10) ;
    divisor = grib_power(-binary_scale_factor,2);

    buflen = (((bits_per_value*n_vals)+7)/8)*sizeof(unsigned char);
    if((buflen + (offsetdata-offsetsection)) %2) {
        buflen++;
        /*
    a->length++;
    a->parent->h->buffer->ulength++;
         */
    }
    half_byte = (buflen*8)-((*len)*bits_per_value);
    grib_context_log(a->parent->h->context,GRIB_LOG_DEBUG,
            "HALF byte: buflen=%d bits_per_value=%ld len=%d half_byte=%ld\n",
            buflen,bits_per_value,*len,half_byte);

    Assert(half_byte <= 0x0f);

    if((ret = grib_set_long_internal(a->parent->h,self->half_byte, half_byte))
            != GRIB_SUCCESS)
        return ret;

    buf = (unsigned char*)grib_context_buffer_malloc_clear(a->parent->h->context,buflen);
    encoded = buf;

    grib_encode_double_array(n_vals,val,bits_per_value,reference_value,decimal,divisor,encoded,&off);

    grib_context_log(a->parent->h->context, GRIB_LOG_DEBUG,
            "grib_accessor_data_g1simple_packing : pack_double : packing %s, %d values", a->name, n_vals);

    grib_buffer_replace(a, buf, buflen,1,1);

    grib_context_buffer_free(a->parent->h->context,buf);

    return GRIB_SUCCESS;
}
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;
}