Exemplo n.º 1
0
static int
encode_complex (int kind,
#ifdef HAVE_mpc
		mpc_t cmplx,
#else
		mpfr_t real, mpfr_t imaginary,
#endif
		unsigned char *buffer, size_t buffer_size)
{
  int size;
  size = encode_float (kind,
#ifdef HAVE_mpc
		       mpc_realref (cmplx),
#else
		       real,
#endif
		       &buffer[0], buffer_size);
  size += encode_float (kind,
#ifdef HAVE_mpc
			mpc_imagref (cmplx),
#else
			imaginary,
#endif
			&buffer[size], buffer_size - size);
  return size;
}
static int
encode_complex (int kind, mpfr_t real, mpfr_t imaginary, unsigned char *buffer,
		size_t buffer_size)
{
  int size;
  size = encode_float (kind, real, &buffer[0], buffer_size);
  size += encode_float (kind, imaginary, &buffer[size], buffer_size - size);
  return size;
}
static int
encode_complex (int kind, mpc_t cmplx,
		unsigned char *buffer, size_t buffer_size)
{
  int size;
  size = encode_float (kind, mpc_realref (cmplx), &buffer[0], buffer_size);
  size += encode_float (kind, mpc_imagref (cmplx),
			&buffer[size], buffer_size - size);
  return size;
}
/* Write a constant expression in binary form to a buffer.  */
int
gfc_target_encode_expr (gfc_expr *source, unsigned char *buffer,
			size_t buffer_size)
{
  if (source == NULL)
    return 0;

  if (source->expr_type == EXPR_ARRAY)
    return encode_array (source, buffer, buffer_size);

  gcc_assert (source->expr_type == EXPR_CONSTANT
	      || source->expr_type == EXPR_STRUCTURE
	      || source->expr_type == EXPR_SUBSTRING);

  /* If we already have a target-memory representation, we use that rather 
     than recreating one.  */
  if (source->representation.string)
    {
      memcpy (buffer, source->representation.string,
	      source->representation.length);
      return source->representation.length;
    }

  switch (source->ts.type)
    {
    case BT_INTEGER:
      return encode_integer (source->ts.kind, source->value.integer, buffer,
			     buffer_size);
    case BT_REAL:
      return encode_float (source->ts.kind, source->value.real, buffer,
			   buffer_size);
    case BT_COMPLEX:
      return encode_complex (source->ts.kind, source->value.complex.r,
			     source->value.complex.i, buffer, buffer_size);
    case BT_LOGICAL:
      return encode_logical (source->ts.kind, source->value.logical, buffer,
			     buffer_size);
    case BT_CHARACTER:
      if (source->expr_type == EXPR_CONSTANT || source->ref == NULL)
	return encode_character (source->value.character.length,
			         source->value.character.string, buffer,
			         buffer_size);
      else
	{
	  int start, end;

	  gcc_assert (source->expr_type == EXPR_SUBSTRING);
	  gfc_extract_int (source->ref->u.ss.start, &start);
	  gfc_extract_int (source->ref->u.ss.end, &end);
	  return encode_character (MAX(end - start + 1, 0),
				   &source->value.character.string[start-1],
				   buffer, buffer_size);
	}
    case BT_DERIVED:
      return encode_derived (source, buffer, buffer_size);
    default:
      gfc_internal_error ("Invalid expression in gfc_target_encode_expr.");
      return 0;
    }
}
Exemplo n.º 5
0
void StreamPeer::put_float(float p_val) {

	uint8_t buf[4];

	encode_float(p_val, buf);
	if (big_endian) {
		uint32_t *p32 = (uint32_t *)buf;
		*p32 = BSWAP32(*p32);
	}

	put_data(buf, 4);
}
Exemplo n.º 6
0
struct byte_array* serial_encode_float(struct byte_array* buf, float value) {
    if (!buf)
        buf = byte_array_new();
    encode_float(buf, value);
    return buf;
}
Exemplo n.º 7
0
Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len) {

	uint8_t *buf = r_buffer;

	r_len = 0;

	uint32_t flags = 0;

	switch (p_variant.get_type()) {

		case Variant::INT: {
			int64_t val = p_variant;
			if (val > 0x7FFFFFFF || val < -0x80000000) {
				flags |= ENCODE_FLAG_64;
			}
		} break;
		case Variant::REAL: {

			double d = p_variant;
			float f = d;
			if (double(f) != d) {
				flags |= ENCODE_FLAG_64; //always encode real as double
			}
		} break;
	}

	if (buf) {
		encode_uint32(p_variant.get_type() | flags, buf);
		buf += 4;
	}
	r_len += 4;

	switch (p_variant.get_type()) {

		case Variant::NIL: {

			//nothing to do
		} break;
		case Variant::BOOL: {

			if (buf) {
				encode_uint32(p_variant.operator bool(), buf);
			}

			r_len += 4;

		} break;
		case Variant::INT: {

			int64_t val = p_variant;
			if (val > 0x7FFFFFFF || val < -0x80000000) {
				//64 bits
				if (buf) {
					encode_uint64(val, buf);
				}

				r_len += 8;
			} else {
				if (buf) {
					encode_uint32(int32_t(val), buf);
				}

				r_len += 4;
			}
		} break;
		case Variant::REAL: {

			double d = p_variant;
			float f = d;
			if (double(f) != d) {
				if (buf) {
					encode_double(p_variant.operator double(), buf);
				}

				r_len += 8;

			} else {

				if (buf) {
					encode_float(p_variant.operator float(), buf);
				}

				r_len += 4;
			}

		} break;
		case Variant::NODE_PATH: {

			NodePath np = p_variant;
			if (buf) {
				encode_uint32(uint32_t(np.get_name_count()) | 0x80000000, buf); //for compatibility with the old format
				encode_uint32(np.get_subname_count(), buf + 4);
				uint32_t flags = 0;
				if (np.is_absolute())
					flags |= 1;
				if (np.get_property() != StringName())
					flags |= 2;

				encode_uint32(flags, buf + 8);

				buf += 12;
			}

			r_len += 12;

			int total = np.get_name_count() + np.get_subname_count();
			if (np.get_property() != StringName())
				total++;

			for (int i = 0; i < total; i++) {

				String str;

				if (i < np.get_name_count())
					str = np.get_name(i);
				else if (i < np.get_name_count() + np.get_subname_count())
					str = np.get_subname(i - np.get_subname_count());
				else
					str = np.get_property();

				CharString utf8 = str.utf8();

				int pad = 0;

				if (utf8.length() % 4)
					pad = 4 - utf8.length() % 4;

				if (buf) {
					encode_uint32(utf8.length(), buf);
					buf += 4;
					copymem(buf, utf8.get_data(), utf8.length());
					buf += pad + utf8.length();
				}

				r_len += 4 + utf8.length() + pad;
			}

		} break;
		case Variant::STRING: {

			CharString utf8 = p_variant.operator String().utf8();

			if (buf) {
				encode_uint32(utf8.length(), buf);
				buf += 4;
				copymem(buf, utf8.get_data(), utf8.length());
			}

			r_len += 4 + utf8.length();
			while (r_len % 4)
				r_len++; //pad

		} break;
		// math types

		case Variant::VECTOR2: {

			if (buf) {
				Vector2 v2 = p_variant;
				encode_float(v2.x, &buf[0]);
				encode_float(v2.y, &buf[4]);
			}

			r_len += 2 * 4;

		} break; // 5
		case Variant::RECT2: {

			if (buf) {
				Rect2 r2 = p_variant;
				encode_float(r2.position.x, &buf[0]);
				encode_float(r2.position.y, &buf[4]);
				encode_float(r2.size.x, &buf[8]);
				encode_float(r2.size.y, &buf[12]);
			}
			r_len += 4 * 4;

		} break;
		case Variant::VECTOR3: {

			if (buf) {
				Vector3 v3 = p_variant;
				encode_float(v3.x, &buf[0]);
				encode_float(v3.y, &buf[4]);
				encode_float(v3.z, &buf[8]);
			}

			r_len += 3 * 4;

		} break;
		case Variant::TRANSFORM2D: {

			if (buf) {
				Transform2D val = p_variant;
				for (int i = 0; i < 3; i++) {
					for (int j = 0; j < 2; j++) {

						copymem(&buf[(i * 2 + j) * 4], &val.elements[i][j], sizeof(float));
					}
				}
			}

			r_len += 6 * 4;

		} break;
		case Variant::PLANE: {

			if (buf) {
				Plane p = p_variant;
				encode_float(p.normal.x, &buf[0]);
				encode_float(p.normal.y, &buf[4]);
				encode_float(p.normal.z, &buf[8]);
				encode_float(p.d, &buf[12]);
			}

			r_len += 4 * 4;

		} break;
		case Variant::QUAT: {

			if (buf) {
				Quat q = p_variant;
				encode_float(q.x, &buf[0]);
				encode_float(q.y, &buf[4]);
				encode_float(q.z, &buf[8]);
				encode_float(q.w, &buf[12]);
			}

			r_len += 4 * 4;

		} break;
		case Variant::RECT3: {

			if (buf) {
				Rect3 aabb = p_variant;
				encode_float(aabb.position.x, &buf[0]);
				encode_float(aabb.position.y, &buf[4]);
				encode_float(aabb.position.z, &buf[8]);
				encode_float(aabb.size.x, &buf[12]);
				encode_float(aabb.size.y, &buf[16]);
				encode_float(aabb.size.z, &buf[20]);
			}

			r_len += 6 * 4;

		} break;
		case Variant::BASIS: {

			if (buf) {
				Basis val = p_variant;
				for (int i = 0; i < 3; i++) {
					for (int j = 0; j < 3; j++) {

						copymem(&buf[(i * 3 + j) * 4], &val.elements[i][j], sizeof(float));
					}
				}
			}

			r_len += 9 * 4;

		} break;
		case Variant::TRANSFORM: {

			if (buf) {
				Transform val = p_variant;
				for (int i = 0; i < 3; i++) {
					for (int j = 0; j < 3; j++) {

						copymem(&buf[(i * 3 + j) * 4], &val.basis.elements[i][j], sizeof(float));
					}
				}

				encode_float(val.origin.x, &buf[36]);
				encode_float(val.origin.y, &buf[40]);
				encode_float(val.origin.z, &buf[44]);
			}

			r_len += 12 * 4;

		} break;

		// misc types
		case Variant::COLOR: {

			if (buf) {
				Color c = p_variant;
				encode_float(c.r, &buf[0]);
				encode_float(c.g, &buf[4]);
				encode_float(c.b, &buf[8]);
				encode_float(c.a, &buf[12]);
			}

			r_len += 4 * 4;

		} break;
		/*case Variant::RESOURCE: {

			ERR_EXPLAIN("Can't marshallize resources");
			ERR_FAIL_V(ERR_INVALID_DATA); //no, i'm sorry, no go
		} break;*/
		case Variant::_RID:
		case Variant::OBJECT: {

		} break;
		case Variant::DICTIONARY: {

			Dictionary d = p_variant;

			if (buf) {
				encode_uint32(uint32_t(d.size()), buf);
				buf += 4;
			}
			r_len += 4;

			List<Variant> keys;
			d.get_key_list(&keys);

			for (List<Variant>::Element *E = keys.front(); E; E = E->next()) {

				/*
				CharString utf8 = E->->utf8();

				if (buf) {
					encode_uint32(utf8.length()+1,buf);
					buf+=4;
					copymem(buf,utf8.get_data(),utf8.length()+1);
				}

				r_len+=4+utf8.length()+1;
				while (r_len%4)
					r_len++; //pad
				*/
				int len;
				encode_variant(E->get(), buf, len);
				ERR_FAIL_COND_V(len % 4, ERR_BUG);
				r_len += len;
				if (buf)
					buf += len;
				encode_variant(d[E->get()], buf, len);
				ERR_FAIL_COND_V(len % 4, ERR_BUG);
				r_len += len;
				if (buf)
					buf += len;
			}

		} break;
		case Variant::ARRAY: {

			Array v = p_variant;

			if (buf) {
				encode_uint32(uint32_t(v.size()), buf);
				buf += 4;
			}

			r_len += 4;

			for (int i = 0; i < v.size(); i++) {

				int len;
				encode_variant(v.get(i), buf, len);
				ERR_FAIL_COND_V(len % 4, ERR_BUG);
				r_len += len;
				if (buf)
					buf += len;
			}

		} break;
		// arrays
		case Variant::POOL_BYTE_ARRAY: {

			PoolVector<uint8_t> data = p_variant;
			int datalen = data.size();
			int datasize = sizeof(uint8_t);

			if (buf) {
				encode_uint32(datalen, buf);
				buf += 4;
				PoolVector<uint8_t>::Read r = data.read();
				copymem(buf, &r[0], datalen * datasize);
			}

			r_len += 4 + datalen * datasize;
			while (r_len % 4)
				r_len++;

		} break;
		case Variant::POOL_INT_ARRAY: {

			PoolVector<int> data = p_variant;
			int datalen = data.size();
			int datasize = sizeof(int32_t);

			if (buf) {
				encode_uint32(datalen, buf);
				buf += 4;
				PoolVector<int>::Read r = data.read();
				for (int i = 0; i < datalen; i++)
					encode_uint32(r[i], &buf[i * datasize]);
			}

			r_len += 4 + datalen * datasize;

		} break;
		case Variant::POOL_REAL_ARRAY: {

			PoolVector<real_t> data = p_variant;
			int datalen = data.size();
			int datasize = sizeof(real_t);

			if (buf) {
				encode_uint32(datalen, buf);
				buf += 4;
				PoolVector<real_t>::Read r = data.read();
				for (int i = 0; i < datalen; i++)
					encode_float(r[i], &buf[i * datasize]);
			}

			r_len += 4 + datalen * datasize;

		} break;
		case Variant::POOL_STRING_ARRAY: {

			PoolVector<String> data = p_variant;
			int len = data.size();

			if (buf) {
				encode_uint32(len, buf);
				buf += 4;
			}

			r_len += 4;

			for (int i = 0; i < len; i++) {

				CharString utf8 = data.get(i).utf8();

				if (buf) {
					encode_uint32(utf8.length() + 1, buf);
					buf += 4;
					copymem(buf, utf8.get_data(), utf8.length() + 1);
					buf += utf8.length() + 1;
				}

				r_len += 4 + utf8.length() + 1;
				while (r_len % 4) {
					r_len++; //pad
					if (buf)
						buf++;
				}
			}

		} break;
		case Variant::POOL_VECTOR2_ARRAY: {

			PoolVector<Vector2> data = p_variant;
			int len = data.size();

			if (buf) {
				encode_uint32(len, buf);
				buf += 4;
			}

			r_len += 4;

			if (buf) {

				for (int i = 0; i < len; i++) {

					Vector2 v = data.get(i);

					encode_float(v.x, &buf[0]);
					encode_float(v.y, &buf[4]);
					buf += 4 * 2;
				}
			}

			r_len += 4 * 2 * len;

		} break;
		case Variant::POOL_VECTOR3_ARRAY: {

			PoolVector<Vector3> data = p_variant;
			int len = data.size();

			if (buf) {
				encode_uint32(len, buf);
				buf += 4;
			}

			r_len += 4;

			if (buf) {

				for (int i = 0; i < len; i++) {

					Vector3 v = data.get(i);

					encode_float(v.x, &buf[0]);
					encode_float(v.y, &buf[4]);
					encode_float(v.z, &buf[8]);
					buf += 4 * 3;
				}
			}

			r_len += 4 * 3 * len;

		} break;
		case Variant::POOL_COLOR_ARRAY: {

			PoolVector<Color> data = p_variant;
			int len = data.size();

			if (buf) {
				encode_uint32(len, buf);
				buf += 4;
			}

			r_len += 4;

			if (buf) {

				for (int i = 0; i < len; i++) {

					Color c = data.get(i);

					encode_float(c.r, &buf[0]);
					encode_float(c.g, &buf[4]);
					encode_float(c.b, &buf[8]);
					encode_float(c.a, &buf[12]);
					buf += 4 * 4;
				}
			}

			r_len += 4 * 4 * len;

		} break;
		default: { ERR_FAIL_V(ERR_BUG); }
	}

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

}