external format

Kent Boortz <>
Mon Nov 6 12:36:37 CET 2000


> Why a four-byte length for a SMALL_BIG_EXT?

It is one byte telling us we have a four byte integer encoded.

> Why isn't LARGE_BIG_EXT used at all?
> 
> Is there any support for the large integers in C code? I didn't find any...
> The GNU MP library could be used here, if needed.

We have no inteface to a specific multiple precision library like GMP.

A possibility could be to add a '--with-gmp' option to configure
and add a function similar to the function below (code not tested).

Maybe there should be a ei_encode_longlong() also where we want a 64
bit integer on a 32 bit machine but don't want to use a bignum
package. Hmm...the code in ei_encode_long() isn't even correct for
a 64 bit machine :-(

kent



#ifdef WITH_GMP

#include <gmp.h>

#ifdef __GNU_MP__ >= 3

int ei_encode_bignum(char *buf, int *index, mpz_t *n)
{
  char *s = buf + *index;
  char *s0 = s;
  size_t limbs = mpz_size(n);
  size_t size_in_bytes = limbs * sizeof(mp_limb_t);
  size_t i;

  /* Could test for small integers and code into ERL_SMALL_INTEGER_EXT
     and ERL_INTEGER_EXT but the format does not require that we code
     into the smallest possible format [XXX but I think it should /kent] */

  if (size_in_bytes < 256) { 
    if (!buf) return 3 + size_in_bytes;
    put8(s,ERL_SMALL_BIG_EXT);
    put8(s,size_in_bytes);     /* length fits into one byte */
    put8(s, mpz_sgn(n) < 0);   /* save sign separately */
  } else {
    if (!buf) return 6 + size_in_bytes;
    put8(s,ERL_LARGE_BIG_EXT);
    put32be(s,4);              /* XXX not clear that big endian */
    put8(s, mpz_sgn(n) < 0);   /* save sign separately */
  }

  /* XXX In future GMP implementations the limb size will not be
     fixed to 32 or 64 bits */

  /* XXX I assume limb numers starts from 1, do they? */

#ifdef sizeof(mp_limb_t) == 4

  for (i = 1; i <= limbs; i++) {
    mp_limb_t limb = mpz_getlimbn(mpz_t n, mp_size_t i);
    put8(s, limb & 0xff);
    put8(s, (limb >> 8) & 0xff);
    put8(s, (limb >> 16) & 0xff);
    put8(s, (limb >> 24) & 0xff);
  }

#else
#ifdef sizeof(mp_limb_t) == 8

  for (i = 1; i <= limbs; i++) {
    mp_limb_t limb = mpz_getlimbn(mpz_t n, mp_size_t i);
    put8(s, limb & 0xff);
    put8(s, (limb >> 8) & 0xff);
    put8(s, (limb >> 16) & 0xff);
    put8(s, (limb >> 24) & 0xff);
    put8(s, (limb >> 32) & 0xff);
    put8(s, (limb >> 40) & 0xff);
    put8(s, (limb >> 48) & 0xff);
    put8(s, (limb >> 56) & 0xff);
  }

#else

This is an error.......

#endif /* limb size 8 */
#endif /* limb size 4 */
 
  *index += s-s0;
 
  return 0;
}

#endif /* __GNU_MP__ >= 3 */

#endif /* WITH_GMP */



More information about the erlang-questions mailing list