static int pack_long(grib_accessor* a, const long* val, size_t *len)
{
  grib_accessor_element* self = (grib_accessor_element*)a;
  int ret = 0;
  size_t size=0;
  long* ar=NULL;
  grib_context* c=a->parent->h->context;

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

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

  ar=grib_context_malloc_clear(c,size*sizeof(long));
  if (!ar) {
    grib_context_log(c,GRIB_LOG_ERROR,"unable to allocate %d bytes",size*sizeof(long));
    return GRIB_OUT_OF_MEMORY;
  }
  
  if((ret = grib_get_long_array_internal(a->parent->h, self->array,ar,&size)) != GRIB_SUCCESS)
    return ret;

  
  ar[self->element]=*val;

  if((ret = grib_set_long_array_internal(a->parent->h, self->array,ar,size)) != GRIB_SUCCESS)
    return ret;

  grib_context_free(c,ar);
  return ret;
}
static int  unpack_long(grib_accessor* a, long* val, size_t *len)
{
  int ret=GRIB_SUCCESS;
  long ni=0,nj=0,plpresent=0;
  size_t plsize=0;
  long* pl;
  int i;
  grib_accessor_number_of_points* self = (grib_accessor_number_of_points*)a;
  grib_context* c=a->context;

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

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

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

  if (nj == 0) return GRIB_GEOCALCULUS_PROBLEM;

  if (plpresent) {
    /*reduced*/
    plsize=nj;
    pl=(long*)grib_context_malloc(c,sizeof(long)*plsize);
    grib_get_long_array_internal(grib_handle_of_accessor(a),self->pl,pl, &plsize);
    *val=0;
    for (i=0;i<plsize;i++) *val+=pl[i];
	grib_context_free(c,pl);
  } else {
    /*regular*/
    *val=ni*nj;
  }

  return ret;
}
static int init(grib_iterator* iter,grib_handle* h,grib_arguments* args)
{
  int ret=GRIB_SUCCESS,j;
  double lat_first=0,lon_first=0,lat_last=0,lon_last=0,d=0;
  double* lats;
  size_t plsize=0;
  int l=0;
  long* pl;
  long nj=0,order=0,ilon_first,ilon_last,i;
  long row_count=0;
  grib_context* c=h->context;
  grib_iterator_gaussian_reduced* self = (grib_iterator_gaussian_reduced*)iter;
  const char* slat_first   = grib_arguments_get_name(h,args,self->carg++);
  const char* slon_first   = grib_arguments_get_name(h,args,self->carg++);
  const char* slat_last    = grib_arguments_get_name(h,args,self->carg++);
  const char* slon_last    = grib_arguments_get_name(h,args,self->carg++);
  const char* sorder       = grib_arguments_get_name(h,args,self->carg++);
  const char* spl          = grib_arguments_get_name(h,args,self->carg++);
  const char* snj          = grib_arguments_get_name(h,args,self->carg++);

  if((ret = grib_get_double_internal(h, slat_first,&lat_first)) != GRIB_SUCCESS)
    return ret;
  if((ret = grib_get_double_internal(h, slon_first,&lon_first)) != GRIB_SUCCESS)
    return ret;
  if((ret = grib_get_double_internal(h, slat_last,&lat_last)) != GRIB_SUCCESS)
    return ret;
  if((ret = grib_get_double_internal(h, slon_last,&lon_last)) != GRIB_SUCCESS)
    return ret;

  if((ret = grib_get_long_internal(h, sorder,&order)) != GRIB_SUCCESS)
    return ret;
  if((ret = grib_get_long_internal(h, snj,&nj)) != GRIB_SUCCESS)
    return ret;

  lats=(double*)grib_context_malloc(h->context,sizeof(double)*order*2);
  if((ret = grib_get_gaussian_latitudes(order, lats)) != GRIB_SUCCESS)
      return ret;

  if((ret = grib_get_size(h,spl,&plsize)) != GRIB_SUCCESS)
      return ret;

  pl=(long*)grib_context_malloc(c,sizeof(long)*plsize);
  grib_get_long_array_internal(h,spl,pl, &plsize);

  self->las = grib_context_malloc(h->context,iter->nv*sizeof(double));
  self->los = grib_context_malloc(h->context,iter->nv*sizeof(double));

  while (lon_last<0) lon_last+=360;
  while (lon_first<0) lon_first+=360;

  d=fabs(lats[0]-lats[1]);
  if ( (fabs(lat_first-lats[0]) >= d ) ||
       (fabs(lat_last+lats[0]) >= d )  ||
       lon_first != 0                 ||
       fabs(lon_last  - (360.0-90.0/order)) > 90.0/order
       ) {
    /*sub area*/
	/*find starting latitude */
	while (fabs(lat_first-lats[l]) > d ) {l++;}
    iter->e=0;
    for (j=0;j<plsize;j++) {
        row_count=0;
		/*printf("lat=%g\n",lats[j+l]);*/
		grib_get_reduced_row(pl[j],lon_first,lon_last,
                  &row_count,&ilon_first,&ilon_last);
        if (ilon_first>ilon_last) ilon_first-=pl[j];
        for (i=ilon_first;i<=ilon_last;i++) {
         self->los[iter->e]=((i)*360.0)/pl[j];
         self->las[iter->e]=lats[j+l];
         iter->e++;
        }
     }
  } else {
    /*global*/
    iter->e=0;
    for (j=0;j<plsize;j++) {
        row_count=pl[j];
        for (i=0;i<row_count;i++) {
         self->los[iter->e]=(i*360.0)/row_count;
         self->las[iter->e]=lats[j];
         iter->e++;
        }
     }
  }

  iter->e = -1;
  grib_context_free(h->context,lats);
  grib_context_free(h->context,pl);

  return ret;
}
static int init(grib_iterator* i,grib_handle* h,grib_arguments* args)
{
	grib_iterator_latlon_reduced* self = (grib_iterator_latlon_reduced*)i;

	int ret = GRIB_SUCCESS;
	double laf;
	double lal;
	long nlats;
	double lof,tlof;
	double lol,dimin;
	long *pl;
	size_t plsize =0 ;
	long k,j,ii;
	long nlons,plmax;
	double jdirinc = 0;
	double idirinc = 0;
	double dlon=0;
	int islocal=0;
	long nlons2 =0; /* adjusted num of longitudes */

	const char* latofirst   = grib_arguments_get_name(h,args,self->carg++);
	const char* longoffirst = grib_arguments_get_name(h,args,self->carg++);
	const char* latoflast   = grib_arguments_get_name(h,args,self->carg++);
	const char* longoflast  = grib_arguments_get_name(h,args,self->carg++);
	const char* nlats_name    = grib_arguments_get_name(h,args,self->carg++);
	const char* jdirec      = grib_arguments_get_name(h,args,self->carg++);
	const char* plac        = grib_arguments_get_name(h,args,self->carg++);

	if(( ret = grib_get_double_internal(h,latofirst,      &laf))) return ret;
	if(( ret = grib_get_double_internal(h,longoffirst,    &lof))) return ret;

	if(( ret = grib_get_double_internal(h,latoflast,     &lal))) return ret;
	if(( ret = grib_get_double_internal(h,longoflast,    &lol))) return ret;

	if(( ret = grib_get_long_internal(h,nlats_name,&nlats))) return ret;

	if(( ret = grib_get_double_internal(h,jdirec,&jdirinc))) return ret;

	plsize = nlats;
	pl  = (long*)grib_context_malloc(h->context,plsize*sizeof(long));
	grib_get_long_array_internal(h,plac,pl, &plsize);

	self->las = (double*)grib_context_malloc(h->context,i->nv*sizeof(double));
	self->los = (double*)grib_context_malloc(h->context,i->nv*sizeof(double));

	plmax=pl[0];
	for (j=0;j<nlats;j++) if (plmax<pl[j]) plmax=pl[j];
	dimin=360.0/plmax;

	if ( 360-fabs(lol-lof) < 2 * dimin ) {dlon=360; islocal=0;}
	else if (lol < lof) {
		/* handle something like 150 to -120 to treat as 150 to 240 */
		/* so that dlon is 90 (not -270) */
		dlon=lol + 360.0 - lof;
		islocal=1;
	}
	else {dlon=lol-lof; islocal=1;}

	if (laf>lal) jdirinc=-jdirinc;
	k=0;
	for (j=0;j<nlats;j++) {
		nlons=pl[j];
		tlof=lof;
		nlons2 = nlons-islocal;
		/*Sometimes there are no points on a latitude! Protect against div by zero*/
		if (nlons2<1) nlons2=1;
		idirinc=dlon/nlons2;
		for (ii=0;ii<nlons;ii++) {
			self->las[k]=laf;
			self->los[k]=tlof;
			tlof+=idirinc;
			k++;
		}
		laf+=jdirinc;
	}

	i->e = -1;
	grib_context_free(h->context,pl);

	return ret;
}
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 pack_double(grib_accessor* a, const 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;
    }

    valuesSize=numberOfPoints;

    values=(double*)grib_context_malloc_clear(a->context,sizeof(double)*numberOfPoints);

    pvalues=values;
    pval=(double*)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) {
                pvalues+=pl[j];
                for (i=0;i<pl[j] ;i++) { *(--pvalues)=*(pval++); }
                pvalues+=pl[j];
            } else {
                for (i=0;i<pl[j];i++) *(pvalues++)=*(pval++);
            }
        }

        grib_context_free(a->context,pl);

    } else {

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

    }
    ret=grib_set_double_array_internal(grib_handle_of_accessor(a),self->values,values,valuesSize);
    if (ret) return ret;

    grib_context_free(a->context,values);

    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* 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 init(grib_iterator* iter,grib_handle* h,grib_arguments* args)
{
    int ret=GRIB_SUCCESS, j, is_global=0;
    double lat_first=0,lon_first=0,lat_last=0,lon_last=0;
    double angular_precision = 1.0/1000000.0;
    double* lats;
    size_t plsize=0;
    long* pl;
    long max_pl=0;
    long nj=0,order=0,ilon_first,ilon_last,i;
    long row_count=0;
    long editionNumber = 0;
    grib_context* c=h->context;
    grib_iterator_gaussian_reduced* self = (grib_iterator_gaussian_reduced*)iter;
    const char* slat_first   = grib_arguments_get_name(h,args,self->carg++);
    const char* slon_first   = grib_arguments_get_name(h,args,self->carg++);
    const char* slat_last    = grib_arguments_get_name(h,args,self->carg++);
    const char* slon_last    = grib_arguments_get_name(h,args,self->carg++);
    const char* sorder       = grib_arguments_get_name(h,args,self->carg++);
    const char* spl          = grib_arguments_get_name(h,args,self->carg++);
    const char* snj          = grib_arguments_get_name(h,args,self->carg++);

    if((ret = grib_get_double_internal(h, slat_first,&lat_first)) != GRIB_SUCCESS)
        return ret;
    if((ret = grib_get_double_internal(h, slon_first,&lon_first)) != GRIB_SUCCESS)
        return ret;
    if((ret = grib_get_double_internal(h, slat_last,&lat_last)) != GRIB_SUCCESS)
        return ret;
    if((ret = grib_get_double_internal(h, slon_last,&lon_last)) != GRIB_SUCCESS)
        return ret;

    if((ret = grib_get_long_internal(h, sorder,&order)) != GRIB_SUCCESS)
        return ret;
    if((ret = grib_get_long_internal(h, snj,&nj)) != GRIB_SUCCESS)
        return ret;

    if (grib_get_long(h, "editionNumber", &editionNumber)==GRIB_SUCCESS) {
        if (editionNumber == 1) angular_precision = 1.0/1000;
    }

    lats=(double*)grib_context_malloc(h->context,sizeof(double)*order*2);
    if (!lats) return GRIB_OUT_OF_MEMORY;
    if((ret = grib_get_gaussian_latitudes(order, lats)) != GRIB_SUCCESS)
        return ret;

    if((ret = grib_get_size(h,spl,&plsize)) != GRIB_SUCCESS)
        return ret;

    Assert(plsize);
    pl=(long*)grib_context_malloc(c,sizeof(long)*plsize);
    if (!pl) return GRIB_OUT_OF_MEMORY;

    grib_get_long_array_internal(h,spl,pl, &plsize);

    self->las = (double*)grib_context_malloc(h->context,iter->nv*sizeof(double));
    if (!self->las) return GRIB_OUT_OF_MEMORY;
    self->los = (double*)grib_context_malloc(h->context,iter->nv*sizeof(double));
    if (!self->los) return GRIB_OUT_OF_MEMORY;

    while (lon_last<0) lon_last+=360;
    while (lon_first<0) lon_first+=360;

    /* Find the maximum element of "pl" array, do not assume it's 4*N! */
    /* This could be an Octahedral Gaussian Grid */
    max_pl = pl[0];
    for (j=1; j<plsize; j++) {
        if (pl[j] > max_pl) max_pl = pl[j];
    }

    is_global = is_gaussian_global(lat_first, lat_last, lon_first, lon_last, max_pl, lats, angular_precision);
    if ( !is_global ) {
        int l=0;
        /*sub area*/
        /*find starting latitude */
        const double d = fabs(lats[0] - lats[1]);
        while (fabs(lat_first-lats[l]) > d ) {l++;}
        iter->e=0;
        for (j=0;j<plsize;j++) {
            row_count=0;
            grib_get_reduced_row(pl[j],lon_first,lon_last,
                    &row_count,&ilon_first,&ilon_last);
            if (ilon_first>ilon_last) ilon_first-=pl[j];
            for (i=ilon_first;i<=ilon_last;i++) {
#ifdef DEBUG
                Assert(iter->e < iter->nv);
#endif
                self->los[iter->e]=((i)*360.0)/pl[j];
                self->las[iter->e]=lats[j+l];
                iter->e++;
            }
        }
    } else {
        /*global*/
        iter->e=0;
        for (j=0;j<plsize;j++) {
            row_count=pl[j];
            for (i=0;i<row_count;i++) {
#ifdef DEBUG
                Assert(iter->e < iter->nv);
#endif
                self->los[iter->e]=(i*360.0)/row_count;
                self->las[iter->e]=lats[j];
                iter->e++;
            }
        }
    }

    iter->e = -1;
    grib_context_free(h->context,lats);
    grib_context_free(h->context,pl);

    return ret;
}