external format
Kent Boortz
kent@REDACTED
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