static int pack_double(grib_accessor* a, const double* val, size_t *len)
{
  grib_accessor_g2latlon* self = (grib_accessor_g2latlon*)a;
  int ret = 0;

  double grid[6];
  size_t size = 6;

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

  if(self->given)
  {
    long given        = *val != GRIB_MISSING_DOUBLE;
    if((ret = grib_set_long_internal(a->parent->h, self->given,given)) != GRIB_SUCCESS)
      return ret;
  }


  if((ret = grib_get_double_array_internal(a->parent->h, self->grid,grid,&size)) != GRIB_SUCCESS)
    return ret;

  if ( (self->index == 1 || self->index == 3) && *val < 0 ) grid[self->index] = 360+*val;
  else grid[self->index] = *val;

  return grib_set_double_array_internal(a->parent->h, self->grid,grid,size);
}
static int pack_long(grib_accessor* a, const long* val, size_t *len)
{
  double* values=NULL;
  size_t size=0;
  int ret=0;
  grib_accessor_bits_per_value* self= (grib_accessor_bits_per_value*)a;
  grib_context* c=a->context;
  grib_handle* h=grib_handle_of_accessor(a);

  if ( (ret=grib_get_size(h,self->values,&size)) != GRIB_SUCCESS) return ret;

  values=(double*)grib_context_malloc(c,size*sizeof(double));
  if (!values) return GRIB_OUT_OF_MEMORY;

  if((ret = grib_get_double_array_internal(h,self->values,values,&size))
       != GRIB_SUCCESS) {
        grib_context_free(c,values);
        return ret;
  }

  if((ret = grib_set_long_internal(h, self->bits_per_value,*val))
      != GRIB_SUCCESS) return ret;

  if((ret = grib_set_double_array_internal(h, self->values,values,size))
      != GRIB_SUCCESS) return ret;

  grib_context_free(c,values);

  return GRIB_SUCCESS;
}
static int  unpack_double(grib_accessor* a, double* val, size_t *len)
{
  grib_accessor_data_g2shsimple_packing* self =  (grib_accessor_data_g2shsimple_packing*)a;
  int err =  GRIB_SUCCESS;

  size_t n_vals = 0;

  if((err = grib_get_size(grib_handle_of_accessor(a),self->coded_values,&n_vals)) != GRIB_SUCCESS)
    return err;

  self->dirty=0;

    /* n_vals = coded_n_vals+1; */

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

  if((err = grib_get_double_internal(grib_handle_of_accessor(a),self->real_part,val)) != GRIB_SUCCESS)
    return err;

  val++;

  if((err = grib_get_double_array_internal(grib_handle_of_accessor(a),self->coded_values,val,&n_vals)) != GRIB_SUCCESS)
    return err;

  *len =  n_vals;

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

  long given        = 1;
  double grid[6];
  size_t size = 6;

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

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

  if(!given)
  {
    *val =  GRIB_MISSING_DOUBLE;
    return GRIB_SUCCESS;
  }


  if((ret = grib_get_double_array_internal(a->parent->h, self->grid,grid,&size)) != GRIB_SUCCESS)
    return ret;

  *val = grid[self->index];

  return GRIB_SUCCESS;
}
static int  unpack_double(grib_accessor* a, double* val, size_t *len)
{
    grib_accessor_data_g1shsimple_packing* self =  (grib_accessor_data_g1shsimple_packing*)a;
    int err =  GRIB_SUCCESS;

    size_t coded_n_vals = 0;
    size_t n_vals = 0;

    if((err = grib_get_size(a->parent->h,self->coded_values,&coded_n_vals)) != GRIB_SUCCESS)
        return err;

    n_vals = coded_n_vals + 1;

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

    if((err = grib_get_double_internal(a->parent->h,self->real_part,val)) != GRIB_SUCCESS)
        return err;

    val++;

    if((err = grib_get_double_array_internal(a->parent->h,self->coded_values,val,&coded_n_vals)) != GRIB_SUCCESS)
        return err;

    grib_context_log(a->parent->h->context, GRIB_LOG_DEBUG,
            "grib_accessor_data_g1shsimple_packing_bitmap : unpack_double : creating %s, %d values",
            a->name, n_vals);

    *len =  n_vals;

    return err;
}
Example #6
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;
}
static int pack_double(grib_accessor* a, const double* val, size_t *len)
{
    double* values=NULL;
    size_t size=0;
    double missingValue=0;
    long missingValuesPresent = 0;
    int ret=0,i=0;
    grib_accessor_offset_values* self= (grib_accessor_offset_values*)a;
    grib_context* c=a->context;
    grib_handle* h=grib_handle_of_accessor(a);

    if (*val==0) return GRIB_SUCCESS;

    if((ret = grib_get_double_internal(h,self->missingValue,&missingValue)) != GRIB_SUCCESS) {
        return ret;
    }
    if((ret=grib_get_long_internal(h,"missingValuesPresent",&missingValuesPresent)) != GRIB_SUCCESS) {
        return ret;
    }

    if ( (ret=grib_get_size(h,self->values,&size)) != GRIB_SUCCESS) return ret;

    values=(double*)grib_context_malloc(c,size*sizeof(double));
    if (!values) return GRIB_OUT_OF_MEMORY;

    if((ret = grib_get_double_array_internal(h,self->values,values,&size)) != GRIB_SUCCESS) {
        grib_context_free(c,values);
        return ret;
    }

    for (i=0;i<size;i++) {
        if (missingValuesPresent) {
            if (values[i]!=missingValue) values[i]+=*val;
        } else {
            values[i]+=*val;
        }
    }

    if((ret = grib_set_double_array_internal(h, self->values,values,size)) != GRIB_SUCCESS) return ret;

    grib_context_free(c,values);

    return GRIB_SUCCESS;
}
static int    pack_long   (grib_accessor* a, const long* val, size_t *len)
{
  long missing=255;
  int ret=0;
  size_t size=0;
  double* values;
  grib_context* c=a->parent->h->context;
  grib_handle* h=a->parent->h;
  grib_accessor_gds_is_present* self = (grib_accessor_gds_is_present*)a;

  if (*val != 1) return GRIB_NOT_IMPLEMENTED;

  if ( (ret=grib_get_size(h,self->values,&size)) != GRIB_SUCCESS) return ret;

  values=(double*)grib_context_malloc(c,size*sizeof(double));
  if (!values) return GRIB_OUT_OF_MEMORY;

  if((ret = grib_get_double_array_internal(h,self->values,values,&size))
       != GRIB_SUCCESS) {
        grib_context_free(c,values);
        return ret;
  }

  if((ret = grib_set_long_internal(h, self->gds_present,*val))
      != GRIB_SUCCESS) return ret;

  if((ret = grib_set_long_internal(h, self->bitmap_present,*val))
      != GRIB_SUCCESS) return ret;



  if((ret = grib_set_long_internal(h, self->grid_definition,missing))
      != GRIB_SUCCESS) return ret;

  if((ret = grib_set_double_array_internal(h, self->values,values,size))
      != GRIB_SUCCESS) return ret;

  grib_context_free(c,values);

  return GRIB_SUCCESS;
}
static int pack_double(grib_accessor* a, const double* val, size_t *len)
{
  double* values=NULL;
  double missingValue=0;
  size_t size=0;
  int ret=0,i=0;
  grib_accessor_scale_values* self= (grib_accessor_scale_values*)a;
  grib_context* c=a->parent->h->context;
  grib_handle* h=a->parent->h;

  if (*val==1) return GRIB_SUCCESS;

  if((ret = grib_get_double_internal(h,self->missingValue,&missingValue))
       != GRIB_SUCCESS) {
        return ret;
  }

  if ( (ret=grib_get_size(h,self->values,&size)) != GRIB_SUCCESS) return ret;

  values=(double*)grib_context_malloc(c,size*sizeof(double));
  if (!values) return GRIB_OUT_OF_MEMORY;

  if((ret = grib_get_double_array_internal(h,self->values,values,&size))
       != GRIB_SUCCESS) {
        grib_context_free(c,values);
        return ret;
  }

  for (i=0;i<size;i++)
    if (values[i]!=missingValue) values[i]*=*val;

  if((ret = grib_set_double_array_internal(h, self->values,values,size))
      != GRIB_SUCCESS) return ret;

  grib_context_free(c,values);

  return GRIB_SUCCESS;
}
static int unpack_double_element(grib_accessor* a, size_t idx,double* val)
{
    grib_accessor_data_apply_boustrophedonic_bitmap* self =  (grib_accessor_data_apply_boustrophedonic_bitmap*)a;
    int err = 0,i=0;
    size_t cidx=0;
    double missing_value = 0;
    double* bvals=NULL;
    size_t n_vals = 0;
    long nn=0;

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

    if(!grib_find_accessor(a->parent->h,self->bitmap))
        return grib_get_double_element_internal(a->parent->h,self->coded_values,idx,val);

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

    if((err = grib_get_double_element_internal(a->parent->h,self->bitmap,idx,val)) != GRIB_SUCCESS)
        return err;

    if (*val == 0) {*val=missing_value;return GRIB_SUCCESS;}

    bvals = (double*)grib_context_malloc(a->parent->h->context,n_vals*sizeof(double));
    if(bvals == NULL) return GRIB_OUT_OF_MEMORY;

    if((err = grib_get_double_array_internal(a->parent->h,self->bitmap,bvals,&n_vals)) != GRIB_SUCCESS)
        return err;

    cidx=0;
    for (i=0;i<idx;i++) {cidx+=bvals[i];}

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

    return grib_get_double_element_internal(a->parent->h,self->coded_values,cidx,val);
}
static int init(grib_iterator* i,grib_handle *h, grib_arguments* args)
{
  grib_iterator_gen* self = (grib_iterator_gen*) i;
  size_t dli=0;
  int ret = GRIB_SUCCESS;
  const char* rawdat  = NULL;
  const char* snumberOfPoints=NULL;
  long numberOfPoints=0;
  self->carg = 1;
  
  snumberOfPoints = grib_arguments_get_name(h,args,self->carg++);
  self->missingValue  = grib_arguments_get_name(h,args,self->carg++);
  rawdat      = grib_arguments_get_name(h,args,self->carg++);

  i->h    = h; /* We may not need to keep them */
  i->args = args;
  if( (ret =  grib_get_size(h,rawdat,&dli))!= GRIB_SUCCESS) return ret;

  if( (ret =  grib_get_long_internal(h,snumberOfPoints,&numberOfPoints))
       != GRIB_SUCCESS)
    return ret;

  if (numberOfPoints!=dli) {
    grib_context_log(h->context,GRIB_LOG_ERROR,"%s != size(%s) (%ld!=%ld)",
                     snumberOfPoints,rawdat,numberOfPoints,dli);
    return GRIB_WRONG_GRID;
  }
  i->nv = dli;
  i->data = (double*)grib_context_malloc(h->context,(i->nv)*sizeof(double));

  if( (ret = grib_get_double_array_internal(h,rawdat,i->data ,&(i->nv))))
    return ret;

  i->e = -1;

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

  long number_of_points=0,number_of_values=0,ni=0;
  long latitude_of_first_point=0;
  size_t i = 0;
  size_t  n_vals = 0;
  long nn=0;
  int err=0;
  size_t size=0;
  long missing_value;

  double* coded_vals = NULL;

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

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

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

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

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

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

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

  if(number_of_values > 0){
    coded_vals = (double*)grib_context_malloc(a->parent->h->context,number_of_values*sizeof(double));

    if(coded_vals == NULL)
      return GRIB_OUT_OF_MEMORY;
  }

  size=number_of_values;
  if((err=grib_get_double_array_internal(a->parent->h,self->coded_values,coded_vals,&size))
    != GRIB_SUCCESS)  {
    grib_context_free(a->parent->h->context,coded_vals);
    return err;
  }
  if (number_of_values!=size) {
    grib_context_log(a->parent->h->context, GRIB_LOG_ERROR,
      "grib_accessor_data_apply_gdsnotpresent : wrong numberOfValues %ld != %ld",
      number_of_values,size);
  }

  grib_context_log(a->parent->h->context, GRIB_LOG_DEBUG,
      "grib_accessor_data_apply_gdsnotpresent : unpack_double : creating %s, %d values",
      a->name, number_of_points);

  if (latitude_of_first_point == 0) {
    for (i=0;i < number_of_values;i++) val[i]=coded_vals[i];
    for (i=number_of_values;i<number_of_points;i++)
      val[i]=coded_vals[number_of_values-1];
  } else {
    for(i=0;i<ni-1;i++) val[i]=coded_vals[0];
    for(i=ni-1;i<number_of_points;i++) val[i]=coded_vals[i-ni+1];
  }

  *len =  number_of_points;

  grib_context_free(a->parent->h->context,coded_vals);
  return err;
}
int grib_init_accessor_from_handle(grib_loader* loader,grib_accessor* ga,grib_arguments* default_value)
{
	grib_handle* h = (grib_handle*)loader->data;
	int ret = GRIB_SUCCESS;
	size_t len = 0;
	char*   sval = NULL;
	unsigned char*   uval = NULL;
	long*   lval = NULL;
	double* dval = NULL;
	static int first  = 1;
	static const char* missing = 0;
	const char* name = NULL;
	int k = 0;
	grib_handle *g;
	int e, pack_missing = 0;
	grib_context_log(h->context,GRIB_LOG_DEBUG, "XXXXX Copying  %s",   ga->name);

	if(default_value)
	{
		grib_context_log(h->context,GRIB_LOG_DEBUG, "Copying:  setting %s to default value",
				ga->name);
		grib_pack_expression(ga,grib_arguments_get_expression(h,default_value,0));
	}

	if( (ga->flags & GRIB_ACCESSOR_FLAG_NO_COPY)  ||
		 ((ga->flags & GRIB_ACCESSOR_FLAG_EDITION_SPECIFIC) &&
					loader->changing_edition )        ||
		 (ga->flags & GRIB_ACCESSOR_FLAG_FUNCTION) ||
		 ( (ga->flags & GRIB_ACCESSOR_FLAG_READ_ONLY) &&
					!(ga->flags & GRIB_ACCESSOR_FLAG_COPY_OK) ) )
	{
		grib_context_log(h->context,GRIB_LOG_DEBUG, "Copying %s ignored",   ga->name);
		return GRIB_SUCCESS;
	}

#if 0
	if(h->values)
		if(copy_values(h,ga) == GRIB_SUCCESS)
		{
			grib_context_log(h->context,GRIB_LOG_DEBUG, "Copying: setting %s to multi-set-value",   ga->name);
			return GRIB_SUCCESS;
		}
#endif

#if 0
	if(h->loader)
		h->loader->init_accessor(h->loader,ga,default_value);
#else
	/* COMEBACK here
     this is needed if we reparse during reparse....
	 */

	g = h;
	while(g)
	{
		if(g->values) {
			if(copy_values(g,ga) == GRIB_SUCCESS) {
				grib_context_log(h->context,GRIB_LOG_DEBUG, "Copying: setting %s to multi-set-value",   ga->name);
				return GRIB_SUCCESS;
			}
		}
		g = g->main;
	}
#endif

	/* Check if the same name exists in the original message ... */
	k = 0;
	while( (k < MAX_ACCESSOR_NAMES)            &&
			((name = ga->all_names[k]) != NULL) &&
			((ret = grib_get_size(h,name,&len)) != GRIB_SUCCESS)) k++;

	if(ret != GRIB_SUCCESS)
	{
		name = ga->name;

		if(first)
		{
			missing = getenv("GRIB_PRINT_MISSING");
			first = 0;
		}

		grib_context_log(h->context,GRIB_LOG_DEBUG, "Copying [%s] failed: %s",
				name,grib_get_error_message(ret));

		if(missing)
		{
			fprintf(stdout,"REPARSE: no value for %s",name);
			if(default_value)
				fprintf(stdout," (default value)");
			fprintf(stdout,"\n");
		}

		return GRIB_SUCCESS;
	}

	/* we copy also virtual keys*/
	if(len == 0) {
		grib_context_log(h->context,GRIB_LOG_DEBUG, "Copying %s failed, length is 0",   name);
		return GRIB_SUCCESS;
	}

	if((ga->flags & GRIB_ACCESSOR_FLAG_CAN_BE_MISSING) && grib_is_missing(h,name,&e) && e == GRIB_SUCCESS && len == 1)
	{
		grib_pack_missing(ga);
		pack_missing = 1;
	}

	switch(grib_accessor_get_native_type(ga))
	{
	case GRIB_TYPE_STRING:

		/* len = len > 1024 ? len : 1024; */
		grib_get_string_length(h,name,&len);
		sval = (char*)grib_context_malloc(h->context,len);
		ret = grib_get_string_internal(h,name,sval,&len);
		if(ret == GRIB_SUCCESS)
		{
			grib_context_log(h->context,GRIB_LOG_DEBUG, "Copying string %s to %s",  sval, name);
			ret = grib_pack_string(ga,sval,&len);
		}
		grib_context_free(h->context,sval);

		break;

	case GRIB_TYPE_LONG:
		lval = (long*)grib_context_malloc(h->context,len*sizeof(long));
		ret = grib_get_long_array_internal(h,name,lval,&len);
		if(ret == GRIB_SUCCESS)
		{
			grib_context_log(h->context,GRIB_LOG_DEBUG, "Copying %d long(s) %d to %s",  len, lval[0], name);
			if(ga->same)
			{
				ret = grib_set_long_array(ga->parent->h,ga->name,lval,len);

				/* Allow for lists to be resized */
				if((ret == GRIB_WRONG_ARRAY_SIZE || ret == GRIB_ARRAY_TOO_SMALL) && loader->list_is_resized)
					ret = GRIB_SUCCESS;
			}
			else
			{
			    /* See GRIB-492. This is NOT an ideal solution! */
			    if (*lval == GRIB_MISSING_LONG || pack_missing)
			    {
			        ;        /* No checks needed */
			    }
			    else
			    {
			        /* If we have just one key of type long which has one octet, then do not exceed maximum value */
			        const long num_octets = ga->length;
			        if (len == 1 && num_octets == 1 && *lval > 255)
			        {
			            *lval = 0; /* Reset to a reasonable value */
			        }
			    }
				ret = grib_pack_long(ga,lval,&len);
			}
		}

		grib_context_free(h->context,lval);

		break;

	case GRIB_TYPE_DOUBLE:
		dval = (double*)grib_context_malloc(h->context,len*sizeof(double));
		ret = grib_get_double_array_internal(h,name,dval,&len);
		if(ret == GRIB_SUCCESS)
		{
			grib_context_log(h->context,GRIB_LOG_DEBUG, "Copying %d double(s) %g to %s",  len, dval[0], name);
			if(ga->same)
			{
				ret = grib_set_double_array(ga->parent->h,ga->name,dval,len);

				/* Allow for lists to be resized */
				if((ret == GRIB_WRONG_ARRAY_SIZE || ret == GRIB_ARRAY_TOO_SMALL) && loader->list_is_resized)
					ret = GRIB_SUCCESS;
			}
			else ret = grib_pack_double(ga,dval,&len);
		}

		grib_context_free(h->context,dval);
		break;

	case GRIB_TYPE_BYTES:

		uval = (unsigned char*)grib_context_malloc(h->context,len*sizeof(char));
		ret = grib_get_bytes_internal(h,name,uval,&len);
		if(ret == GRIB_SUCCESS)
		{
			grib_context_log(h->context,GRIB_LOG_DEBUG, "Copying %d byte(s) to %s",  len, name);
			ret = grib_pack_bytes(ga,uval,&len);
		}

		grib_context_free(h->context,uval);

		break;

	case GRIB_TYPE_LABEL:
		break;

	default:
		grib_context_log(h->context,GRIB_LOG_ERROR, "Copying %s, cannot establish type %d [%s]"
				, name,grib_accessor_get_native_type(ga),ga->creator->cclass->name);
		break;
	}

	return ret;

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

    size_t i = 0, j = 0, n_vals = 0, irow = 0;
    long nn=0;
    int err=0;
    size_t coded_n_vals = 0;
    double* coded_vals = NULL;
    double missing_value = 0;
    long numberOfPoints, numberOfRows, numberOfColumns;

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

    err=grib_get_long_internal(a->parent->h,self->numberOfRows,&numberOfRows);
    if (err) return err;
    err=grib_get_long_internal(a->parent->h,self->numberOfColumns,&numberOfColumns);
    if (err) return err;
    err=grib_get_long_internal(a->parent->h,self->numberOfPoints,&numberOfPoints);
    if (err) return err;
    Assert(nn == numberOfPoints);

    if(!grib_find_accessor(a->parent->h,self->bitmap))
        return grib_get_double_array_internal(a->parent->h,self->coded_values,val,len);

    if((err = grib_get_size(a->parent->h,self->coded_values,&coded_n_vals)) != GRIB_SUCCESS)
        return err;

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

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

    if (coded_n_vals==0) {
        for(i=0;i < n_vals;i++)
            val[i] = missing_value;

        *len=n_vals;
        return GRIB_SUCCESS;
    }

    if((err = grib_get_double_array_internal(a->parent->h,self->bitmap,val,&n_vals))
            != GRIB_SUCCESS)
        return err;

    coded_vals = (double*)grib_context_malloc(a->parent->h->context,coded_n_vals*sizeof(double));
    if(coded_vals == NULL) return GRIB_OUT_OF_MEMORY;

    if((err = grib_get_double_array_internal(a->parent->h,self->coded_values,coded_vals,&coded_n_vals))
            != GRIB_SUCCESS)
    {
        grib_context_free(a->parent->h->context,coded_vals);
        return err;
    }

    grib_context_log(a->parent->h->context, GRIB_LOG_DEBUG,
            "grib_accessor_class_data_apply_boustrophedonic_bitmap: unpack_double : creating %s, %d values",
            a->name, n_vals);

    /* Boustrophedonic ordering (See GRIB-472):
     * Values on even rank lines (the initial line scanned having rank 1) are swapped
     */
    for(irow=0; irow<numberOfRows; ++irow)
    {
        if (irow%2)
        {
            /* Reverse bitmap entries */
            size_t k = 0;
            size_t start = irow*numberOfColumns;
            size_t end = start + numberOfColumns - 1;
            size_t mid = (numberOfColumns - 1)/2;
            for(k=0; k<mid; ++k)
            {
                /* Swap value at either end */
                double temp = val[start+k];
                val[start+k] = val[end-k];
                val[end-k] = temp;
            }
        }
    }

    for(i=0;i < n_vals;i++)
    {
        if(val[i] == 0 ){
            val[i] = missing_value;
        }
        else
        {
            val[i] = coded_vals[j++];
            if(j>coded_n_vals)
            {
                grib_context_free(a->parent->h->context,coded_vals);
                grib_context_log(a->parent->h->context, GRIB_LOG_ERROR,
                        "grib_accessor_class_data_apply_boustrophedonic_bitmap [%s]:"
                        " unpack_double :  number of coded values does not match bitmap %ld %ld",
                        a->name,coded_n_vals,n_vals);

                return GRIB_ARRAY_TOO_SMALL;
            }
        }
    }

    *len =  n_vals;

    grib_context_free(a->parent->h->context,coded_vals);
    return err;
}
static int    unpack_double   (grib_accessor* a, double* val, size_t *len)
{
  grib_accessor_statistics* self = (grib_accessor_statistics*)a;
  int ret = 0,i=0;
  double* values;
  size_t size=0;
  double max,min,avg,sd,value,skew,kurt,x;
  double missing=0;
  long number_of_missing=0;
  grib_context* c=a->parent->h->context;
  grib_handle* h=a->parent->h;

  if (!a->dirty) return GRIB_SUCCESS;

  if ( (ret=grib_get_size(h,self->values,&size)) != GRIB_SUCCESS) return ret;

  grib_context_log(a->parent->h->context,GRIB_LOG_DEBUG,
    "grib_accessor_statistics: computing statistics for %d values",size);

  if((ret=grib_get_double(a->parent->h,self->missing_value,&missing))
       != GRIB_SUCCESS) return ret;

  values=(double*)grib_context_malloc_clear(c,size*sizeof(double));
  if (!values) return GRIB_OUT_OF_MEMORY;

  if((ret = grib_get_double_array_internal(h,self->values,values,&size))
       != GRIB_SUCCESS) {
        grib_context_free(c,values);
        return ret;
  }

  number_of_missing=0;
  i=0;
  while (i<size && values[i] == missing ) {i++;number_of_missing++;}
  max=values[i];
  min=values[i];
  avg=values[i];
  for (i=number_of_missing+1;i<size;i++) {
    value=values[i];
    if (value > max && value != missing) max=value; 
    if (value < min && value != missing) min=value; 
    if (value != missing) avg+=value;                      
    else number_of_missing++;
  }

  avg/=(size-number_of_missing);

  sd=0; skew=0; kurt=0;
  for (i=0;i<size;i++) {
    if (values[i] != missing) {
      x=(avg-values[i])*(avg-values[i]);
      sd+=x;
      x*=(avg-values[i]);
      skew+=x;
      kurt+=x*(avg-values[i]);
    }
  }

  kurt=kurt;
  if (size-number_of_missing!=0)
	  sd=sqrt(sd/(size-number_of_missing));
  skew=skew;
  
  a->dirty=0;

  grib_context_free(c,values);

  self->v[0]=max;
  self->v[1]=min;
  self->v[2]=avg;
  self->v[3]=number_of_missing;
  self->v[4]=sd;
  self->v[5]=skew;
  self->v[6]=kurt;
  self->v[7]= sd == 0 ? 1 : 0;

  for (i=0;i<self->number_of_elements;i++)
    val[i]=self->v[i];
  
  return ret;
}
static int unpack_double(grib_accessor* a, double* val, size_t *len)
{
    grib_accessor_data_apply_boustrophedonic* self =  (grib_accessor_data_apply_boustrophedonic*)a;
    size_t plSize=0;
    long *pl=0;
    double *values=0;
    double *pvalues=0;
    double *pval=0;
    size_t valuesSize=0;
    long i,j;
    int ret;
    long numberOfPoints,numberOfRows,numberOfColumns;

    ret=grib_get_long_internal(grib_handle_of_accessor(a),self->numberOfPoints,&numberOfPoints);
    if (ret) return ret;

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

    ret=grib_get_size(grib_handle_of_accessor(a),self->values,&valuesSize);
    if (ret) return ret;

    /* constant field */
    if (valuesSize==0) return 0;

    if (valuesSize!=numberOfPoints) {
        grib_context_log(a->context,GRIB_LOG_ERROR,"boustrophedonic ordering error: ( %s=%ld ) != (sizeOf(%s)=%ld)",
                self->numberOfPoints,numberOfPoints,self->values,(long)valuesSize);
        return GRIB_DECODING_ERROR;
    }

    values=(double*)grib_context_malloc_clear(a->context,sizeof(double)*numberOfPoints);
    ret=grib_get_double_array_internal(grib_handle_of_accessor(a),self->values,values,&valuesSize);
    if (ret) return ret;

    pvalues=values;
    pval=val;

    ret=grib_get_long_internal(grib_handle_of_accessor(a),self->numberOfRows,&numberOfRows);
    if (ret) return ret;

    ret=grib_get_long_internal(grib_handle_of_accessor(a),self->numberOfColumns,&numberOfColumns);
    if (ret) return ret;

    if (grib_get_size(grib_handle_of_accessor(a),self->pl,&plSize) == GRIB_SUCCESS) {
        Assert(plSize==numberOfRows);
        pl=(long*)grib_context_malloc_clear(a->context,sizeof(long)*plSize);
        ret=grib_get_long_array_internal(grib_handle_of_accessor(a),self->pl,pl,&plSize);
        if (ret) return ret;

        for (j=0;j<numberOfRows;j++) {
            if (j%2) {
                pval+=pl[j];
                for (i=0;i<pl[j];i++) *(pval--)=*(pvalues++);
                pval+=pl[j];
            } else {
                for (i=0;i<pl[j];i++) *(pval++)=*(pvalues++);
            }
        }

        grib_context_free(a->context,pl);

    } else {

        for (j=0;j<numberOfRows;j++) {
            if (j%2) {
                pval+=numberOfColumns-1;
                for (i=0;i<numberOfColumns;i++) *(pval--)=*(pvalues++);
                pval+=numberOfColumns+1;
            } else {
                for (i=0;i<numberOfColumns;i++) *(pval++)=*(pvalues++);
            }
        }

    }

    grib_context_free(a->context,values);

    return GRIB_SUCCESS;
}
static int    unpack_double   (grib_accessor* a, double* val, size_t *len)
{
  grib_accessor_statistics_spectral* self = (grib_accessor_statistics_spectral*)a;
  int ret = 0,i=0;
  double* values;
  size_t size=0;
  long J,K,M,N;
  double avg,enorm,sd;
  grib_context* c=a->parent->h->context;
  grib_handle* h=a->parent->h;

  if (!a->dirty) return GRIB_SUCCESS;

  if ( (ret=grib_get_size(h,self->values,&size)) != GRIB_SUCCESS) return ret;

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

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

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

  if (J != M || M != K) return GRIB_NOT_IMPLEMENTED;

  N=(M+1)*(M+2)/2;

  if (2*N != size) {
    grib_context_log(a->parent->h->context,GRIB_LOG_ERROR,
                     "wrong number of components for spherical harmonics %ld != %ld",2*N,size);
    return GRIB_WRONG_ARRAY_SIZE;
  }
  
  values=(double*)grib_context_malloc(c,size*sizeof(double));
  if (!values) return GRIB_OUT_OF_MEMORY;

  if((ret = grib_get_double_array_internal(h,self->values,values,&size))
       != GRIB_SUCCESS) {
        grib_context_free(c,values);
        return ret;
  }

  avg=values[0];
  enorm=0;
  sd=0;

  for (i=2; i < 2*J ; i+=2)
    sd += values[i]*values[i];
  
  for (i= 2*J; i < size; i+=2)
    sd += values[i]*values[i] - values[i+1]*values[i+1];

  enorm=sd+avg*avg;

  sd=sqrt(sd);
  enorm=sqrt(enorm);

  a->dirty=0;

  grib_context_free(c,values);
  
  self->v[0]=avg;
  self->v[1]=enorm;
  self->v[2]=sd;
  self->v[3]= sd == 0 ? 1 : 0;

  for (i=0;i<self->number_of_elements;i++)
    val[i]=self->v[i];

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

  size_t i = 0;
  size_t j = 0;
  size_t k = 0;
  size_t m = 0;
  size_t n_vals = 0;
  long nn=0;
  long expand_by =0;
  int err = 0;
  size_t primary_len;
  size_t secondary_len;
  double* primary_vals;
  double* secondary_vals;
  err=grib_value_count(a,&nn);
  n_vals=nn;
  if (err) return err;

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

  if((err = grib_get_long(grib_handle_of_accessor(a),self->expand_by,&expand_by)) != GRIB_SUCCESS)
    return err;

  if((err = grib_get_size(grib_handle_of_accessor(a),self->primary_bitmap,&primary_len)) != GRIB_SUCCESS)
    return err;

  if((err = grib_get_size(grib_handle_of_accessor(a),self->secondary_bitmap,&secondary_len)) != GRIB_SUCCESS)
    return err;

  primary_vals = (double*)grib_context_malloc(a->context,primary_len*sizeof(double));
  if(!primary_vals)
    return GRIB_OUT_OF_MEMORY;

  secondary_vals = (double*)grib_context_malloc(a->context,secondary_len*sizeof(double));
  if(!secondary_vals)
  {
    grib_context_free(a->context,primary_vals);
    return GRIB_OUT_OF_MEMORY;
  }

  if((err = grib_get_double_array_internal(grib_handle_of_accessor(a),self->primary_bitmap,primary_vals,&primary_len)) != GRIB_SUCCESS)
  {
    grib_context_free(a->context,secondary_vals);
    grib_context_free(a->context,primary_vals);
    return err;
  }

  if((err = grib_get_double_array_internal(grib_handle_of_accessor(a),self->secondary_bitmap,secondary_vals,&secondary_len)) != GRIB_SUCCESS)
  {
    grib_context_free(a->context,secondary_vals);
    grib_context_free(a->context,primary_vals);
    return err;
  }

  k = 0;
  m = 0;
  for(i=0;i < primary_len;i++)
  {
    /* if(primary_vals[i]) f++; */
    if(primary_vals[i])
    {
      for(j = 0; j < expand_by; j++)
        val[k++] = secondary_vals[m++];
    }
    else {
      for(j = 0; j < expand_by; j++)
        val[k++] = 0;
    }

  }

  Assert(k <= *len);
  Assert(m <= secondary_len);

  /*printf("FOOBAR %d %d %ld %d\n",f,primary_len,expand_by,n_vals);*/

  *len =  n_vals;

  grib_context_free(a->context,primary_vals);
  grib_context_free(a->context,secondary_vals);
  return err;
}
static int find(grib_nearest* nearest, grib_handle* h,
                double inlat, double inlon,unsigned long flags,
                double* outlats,double* outlons,
                double *values,double *distances,int* indexes, size_t *len) {
  grib_nearest_regular* self = (grib_nearest_regular*) nearest;
  int ret=0,kk=0,ii=0,jj=0;
  size_t nvalues=0;

  long iradius;
  double radius;

  if( (ret =  grib_get_long(h,self->radius,&iradius))!= GRIB_SUCCESS)
    return ret;
  radius=((double)iradius)/1000.0;
  
  if (!nearest->h || (flags & GRIB_NEAREST_SAME_DATA)==0 || nearest->h!=h) {
    grib_iterator* iter=NULL;
    double lat=0,lon=0;

    if( (ret =  grib_get_size(h,self->values_key,&nvalues))!= GRIB_SUCCESS)
       return ret;
    nearest->values_count = nvalues;
    if (nearest->values) grib_context_free(nearest->context,nearest->values);
    nearest->values = grib_context_malloc(h->context,nvalues*sizeof(double));
    if (!nearest->values) return GRIB_OUT_OF_MEMORY;

    ret=grib_get_double_array_internal( h,self->values_key,
                                   nearest->values,&(nearest->values_count));
    if (ret!=GRIB_SUCCESS) grib_context_log(nearest->context,GRIB_LOG_ERROR,
       "nearest: unable to get values array");

    if (!nearest->h || (flags & GRIB_NEAREST_SAME_GRID)==0) {
      double dummy=0;
      double olat=1.e10, olon=1.e10;
      int ilat=0,ilon=0;
      long n=0;

      if( (ret =  grib_get_long(h,self->Ni,&n))!= GRIB_SUCCESS)
       return ret;
      self->lons_count=n;

      if( (ret =  grib_get_long(h,self->Nj,&n))!= GRIB_SUCCESS)
       return ret;
      self->lats_count=n;

      if (self->lats) grib_context_free(nearest->context,self->lats);
      self->lats=grib_context_malloc( nearest->context,
                                 self->lats_count* sizeof(double));
      if (!self->lats) return GRIB_OUT_OF_MEMORY;

      if (self->lons) grib_context_free(nearest->context,self->lons);
      self->lons=grib_context_malloc( nearest->context,
                                 self->lons_count*sizeof(double));
      if (!self->lons) return GRIB_OUT_OF_MEMORY;

      iter=grib_iterator_new(h,0,&ret);
      if (ret) {
          grib_context_log(nearest->context,GRIB_LOG_ERROR,"unable to create iterator");
          return ret;
      }
      while(grib_iterator_next(iter,&lat,&lon,&dummy)) {
        if (olat != lat) {
          self->lats[ilat++]=lat;
          olat=lat;
        }
        if (ilon<self->lons_count && olon != lon) {
          self->lons[ilon++]=lon;
          olon=lon;
        }
      }
      grib_iterator_delete(iter);

    }
    nearest->h=h;

  }

  if (!self->distances || (flags & GRIB_NEAREST_SAME_POINT)==0
                       || (flags & GRIB_NEAREST_SAME_GRID)==0) {

    grib_binary_search(self->lats,self->lats_count-1,inlat,
                                &(self->j[0]),&(self->j[1]));
    grib_binary_search(self->lons,self->lons_count-1,inlon,
                                &(self->i[0]),&(self->i[1]));
    if (!self->distances)
      self->distances=(double*)grib_context_malloc( nearest->context,4*sizeof(double));
    if (!self->k)
      self->k=(int*)grib_context_malloc( nearest->context,4*sizeof(int));
    kk=0;
    for (ii=0;ii<2;ii++) {
      for (jj=0;jj<2;jj++) {
        self->k[kk]=self->i[ii]+self->lons_count*self->j[jj]-1;
        self->distances[kk]=grib_nearest_distance(radius,inlon,inlat,
                     self->lons[self->i[ii]],self->lats[self->j[jj]]);
        kk++;
      }
    }
  }

  kk=0;
  for (ii=0;ii<2;ii++) {
    for (jj=0;jj<2;jj++) {
      distances[kk]=self->distances[kk];
      outlats[kk]=self->lats[self->j[jj]];
      outlons[kk]=self->lons[self->i[ii]];
      values[kk]=nearest->values[self->k[kk]];
      indexes[kk]=self->k[kk];
      kk++;
    }
  }

  return GRIB_SUCCESS;
}
static int find(grib_nearest* nearest, grib_handle* h,
                double inlat, double inlon,unsigned long flags,
                double* outlats,double* outlons, double *values,
                double *distances,double *distances,int *indexes,size_t *len) {
  grib_nearest_reduced* self = (grib_nearest_reduced*) nearest;
  int ret=0,kk=0,ii=0,jj=0;
  double* pl=NULL;
  int ilat;
  size_t nvalues=0;
  if (!nearest->h || (flags & GRIB_NEAREST_SAME_DATA)==0 || nearest->h!=h) {
    grib_iterator* iter=NULL;
    double lat=0,lon=0;

    if( (ret =  grib_get_size(h,self->values_key,&nvalues))!= GRIB_SUCCESS)
       return ret;
    nearest->values_count = nvalues;
    if (nearest->values) grib_context_free(nearest->context,nearest->values);
    nearest->values = grib_context_malloc(h->context,nvalues*sizeof(double));
    if (!nearest->values) return GRIB_OUT_OF_MEMORY;

    ret=grib_get_double_array_internal( h,self->values_key,
                                   nearest->values,&(nearest->values_count));
    if (ret!=GRIB_SUCCESS) grib_context_log(nearest->context,GRIB_LOG_ERROR,
       "nearest: unable to get values array");

    if (!nearest->h || (flags & GRIB_NEAREST_SAME_GRID)==0) {
      double dummy=0;
      double olat=1.e10;
      ilat=0,ilon=0;
      long n=0;

      if (grib_is_missing(h,self->Nj,&ret)) {
        grib_context_log(h->context, GRIB_LOG_DEBUG,"Key '%s' is missing", self->Nj);
        return ret ? ret : GRIB_GEOCALCULUS_PROBLEM;
      }

      if( (ret =  grib_get_long(h,self->Nj,&n))!= GRIB_SUCCESS)
       return ret;
      self->lats_count=n;

      if (self->lats) grib_context_free(nearest->context,self->lats);
      self->lats=grib_context_malloc( nearest->context,
                                 self->lats_count* sizeof(double));
      if (!self->lats) return GRIB_OUT_OF_MEMORY;

      if (self->lons) grib_context_free(nearest->context,self->lons);
      self->lons=grib_context_malloc( nearest->context,
                                 nearest->values_count*sizeof(double));
      if (!self->lons) return GRIB_OUT_OF_MEMORY;

      iter=grib_iterator_new(h,0,&ret);
      while(grib_iterator_next(iter,&lat,&lon,&dummy)) {
        if (olat!=lat) {self->lats[ilat++]=lat;olat=lat;}
        self->lons[ilon++]=lon;
      }
      grib_iterator_delete(iter);
    }
    nearest->h=h;

  }

  if (!self->distances || (flags & GRIB_NEAREST_SAME_POINT)==0
                       || (flags & GRIB_NEAREST_SAME_GRID)==0) {
    double* lons=NULL;
    int nlon=0;
    int plsize=0;

    self->distances=(double*)grib_context_malloc( nearest->context,4*sizeof(double));
    if (!self->distances) return GRIB_OUT_OF_MEMORY;

    grib_binary_search(self->lats,self->lats_count-1,inlat,
                                &(self->j[0]),&(self->j[1]));

    plsize=self->lats_count;
    pl=(double*)grib_context_malloc(h->context,plsize*sizeof(double));
    if (!pl) return GRIB_OUT_OF_MEMORY;
    if( (ret=grib_get_double_array(h,"pl",pl,&plsize))!= GRIB_SUCCESS)
       return ret;

    nlon=0;
    for (jj=0;jj<self->j[0];jj++) {
      nlon+=pl[jj];
    }
    lons=self->lons+nlon;
    grib_binary_search(lons,pl[self->j[0]]-1,inlon,
                                &(self->k[0]),&(self->k[1]));
    self->k[0]+=nlon;
    self->k[1]+=nlon;

    nlon=0;
    for (jj=0;jj<self->j[1];jj++) {
      nlon+=pl[jj];
    }
    lons=self->lons+nlon;
    grib_binary_search(lons,pl[self->j[1]]-1,inlon,
                                &(self->k[2]),&(self->k[3]));
    self->k[2]+=nlon;
    self->k[3]+=nlon;

    kk=0;
    for (ii=0;ii<2;ii++) {
      for (jj=0;jj<2;jj++) {
        self->distances[kk]=grib_nearest_distance(radius,inlon,inlat,
                     self->lons[self->k[kk]],self->lats[self->j[jj]]);
        kk++;
      }
    }

    grib_context_free(h->context,pl);
  }

  kk=0;
  for (ii=0;ii<2;ii++) {
    for (jj=0;jj<2;jj++) {
      distances[kk]=self->distances[kk];
      outlats[kk]=self->lats[self->j[jj]];
      outlons[kk]=self->lons[self->k[kk]];
      values[kk]=nearest->values[self->k[kk]];
      indexes[kk]=self->k[kk];
      kk++;
    }
  }

  return GRIB_SUCCESS;
}
static int pack_long(grib_accessor* a, const long* val, size_t *len)
{
  long bitsPerValue=0;
  double* values=NULL;
  size_t size=0;
  int ret=0;
  grib_accessor_decimal_precision* self= (grib_accessor_decimal_precision*)a;
  grib_context* c=a->parent->h->context;
  grib_handle* h=a->parent->h;

  if (!self->values) {
    if((ret = grib_set_long_internal(h, self->bits_per_value,0))
        != GRIB_SUCCESS) return ret;
        
    if((ret = grib_set_long_internal(h, self->decimal_scale_factor,*val))
        != GRIB_SUCCESS) return ret;

    if((ret = grib_set_long_internal(h, self->changing_precision,1))
        != GRIB_SUCCESS) {
      grib_context_free(c,values);
      return ret;
        }

    return GRIB_SUCCESS;
  }

  if ( (ret=grib_get_size(h,self->values,&size)) != GRIB_SUCCESS) return ret;

  values=(double*)grib_context_malloc(c,size*sizeof(double));
  if (!values) return GRIB_OUT_OF_MEMORY;

  if((ret = grib_get_double_array_internal(h,self->values,values,&size))
       != GRIB_SUCCESS) {
        grib_context_buffer_free(c,values);
        return ret;
  }

  if((ret = grib_set_long_internal(h, self->decimal_scale_factor,*val))
      != GRIB_SUCCESS) { 
        grib_context_buffer_free(c,values);
	  return ret;
	  }

  if((ret = grib_set_long_internal(h, self->bits_per_value,bitsPerValue))
      != GRIB_SUCCESS) {
        grib_context_free(c,values);
	  return ret;
	 }

     if((ret = grib_set_long_internal(h, self->changing_precision,1))
         != GRIB_SUCCESS) {
       grib_context_free(c,values);
       return ret;
         }

  if((ret = grib_set_double_array_internal(h, self->values,values,size))
      != GRIB_SUCCESS) {
        grib_context_buffer_free(c,values);
	  return ret;
	 }

  grib_context_free(c,values);

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

    size_t i = 0;
    size_t j = 0;
    size_t n_vals = 0;
    long nn=0;
    int err=0;
    size_t coded_n_vals = 0;
    double* coded_vals = NULL;
    double missing_value = 0;

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

    if(!grib_find_accessor(a->parent->h,self->bitmap))
        return grib_get_double_array_internal(a->parent->h,self->coded_values,val,len);

    if((err = grib_get_size(a->parent->h,self->coded_values,&coded_n_vals)) != GRIB_SUCCESS)
        return err;

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

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

    if (coded_n_vals==0) {
        for(i=0;i < n_vals;i++)
            val[i] = missing_value;

        *len=n_vals;
        return GRIB_SUCCESS;
    }

    if((err = grib_get_double_array_internal(a->parent->h,self->bitmap,val,&n_vals))
            != GRIB_SUCCESS)
        return err;

    coded_vals = (double*)grib_context_malloc(a->parent->h->context,coded_n_vals*sizeof(double));
    if(coded_vals == NULL) return GRIB_OUT_OF_MEMORY;

    if((err = grib_get_double_array_internal(a->parent->h,self->coded_values,coded_vals,&coded_n_vals))
            != GRIB_SUCCESS)
    {
        grib_context_free(a->parent->h->context,coded_vals);
        return err;
    }

    grib_context_log(a->parent->h->context, GRIB_LOG_DEBUG,
            "grib_accessor_class_data_apply_bitmap: unpack_double : creating %s, %d values",
            a->name, n_vals);

    for(i=0;i < n_vals;i++)
    {
        if(val[i] == 0 ){
            val[i] = missing_value;
        }
        else
        {
            val[i] = coded_vals[j++];
            if(j>coded_n_vals)
            {
                grib_context_free(a->parent->h->context,coded_vals);
                grib_context_log(a->parent->h->context, GRIB_LOG_ERROR,
                        "grib_accessor_class_data_apply_bitmap [%s]:"
                        " unpack_double :  number of coded values does not match bitmap %ld %ld",
                        a->name,coded_n_vals,n_vals);

                return GRIB_ARRAY_TOO_SMALL;
            }
        }
    }

    *len =  n_vals;

    grib_context_free(a->parent->h->context,coded_vals);
    return err;
}