static int    unpack_long   (grib_accessor* a, long* val, size_t *len)
{
    grib_accessor_unsigned_bits* self = (grib_accessor_unsigned_bits*)a;
    int ret=0;
    long pos = a->offset*8;
    long rlen = value_count(a);
    long numberOfBits = 0;

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

    ret=grib_get_long(a->parent->h,self->numberOfBits,&numberOfBits);
    if (ret) return ret;
    if (numberOfBits==0) {
        int i;
        for (i=0; i<rlen; i++) val[i]=0;
        return GRIB_SUCCESS;
    }

    grib_decode_long_array(a->parent->h->buffer->data,&pos,numberOfBits,rlen,val);

    *len = rlen;

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