support new interface between YAP and GMP, so that we don't rely on our own
allocation routines. Several big fixes. git-svn-id: https://yap.svn.sf.net/svnroot/yap/trunk@1490 b08c6af1-5177-4d33-ba66-4b1c6b8b522a
This commit is contained in:
205
C/bignum.c
205
C/bignum.c
@@ -30,182 +30,43 @@ static char SccsId[] = "%W% %G%";
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
/* This global variable tells how things are going */
|
||||
|
||||
static CELL *pre_alloc_base = NULL, *alloc_ptr;
|
||||
|
||||
/* This is a trivial allocator that use the global space:
|
||||
|
||||
Each unit has a:
|
||||
size;
|
||||
nof elements;
|
||||
*/
|
||||
static void *
|
||||
AllocBigNumSpace(size_t size)
|
||||
{
|
||||
void *ret = (void *)(alloc_ptr+1);
|
||||
|
||||
if (pre_alloc_base == NULL) {
|
||||
return((void *)malloc(size));
|
||||
}
|
||||
size = AdjustSize(size)/CellSize;
|
||||
alloc_ptr[0] = size;
|
||||
alloc_ptr += size+1;
|
||||
return(ret);
|
||||
}
|
||||
|
||||
static void *
|
||||
ReAllocBigNumSpace(void *optr, size_t osize, size_t size)
|
||||
{
|
||||
void *out;
|
||||
|
||||
if (pre_alloc_base == NULL) {
|
||||
return((void *)realloc(optr,size));
|
||||
}
|
||||
size = AdjustSize(size)/CellSize;
|
||||
osize = AdjustSize(osize)/CellSize;
|
||||
if (((CELL *)optr)+osize == alloc_ptr) {
|
||||
alloc_ptr += (size-osize);
|
||||
((CELL *)optr)[-1] = size;
|
||||
return(optr);
|
||||
}
|
||||
out = AllocBigNumSpace(size);
|
||||
memcpy(out, (const void *)optr, size*CellSize);
|
||||
return(out);
|
||||
}
|
||||
|
||||
static void
|
||||
FreeBigNumSpace(void *optr, size_t size)
|
||||
{
|
||||
CELL *bp = (CELL *)optr;
|
||||
|
||||
if (pre_alloc_base == NULL) {
|
||||
free(optr);
|
||||
return;
|
||||
}
|
||||
size = AdjustSize(size)/CellSize;
|
||||
if (bp+size == alloc_ptr) {
|
||||
alloc_ptr = bp-1;
|
||||
return;
|
||||
}
|
||||
/* just say it is free */
|
||||
bp[-1] = -bp[-1];
|
||||
}
|
||||
|
||||
MP_INT *
|
||||
Yap_PreAllocBigNum(void)
|
||||
{
|
||||
MP_INT *ret;
|
||||
|
||||
#ifdef USE_GMP
|
||||
/* YAP style memory allocation */
|
||||
mp_set_memory_functions(
|
||||
AllocBigNumSpace,
|
||||
ReAllocBigNumSpace,
|
||||
FreeBigNumSpace);
|
||||
#endif
|
||||
if (pre_alloc_base != H) {
|
||||
/* inform where we are allocating */
|
||||
alloc_ptr = pre_alloc_base = H;
|
||||
}
|
||||
ret = (MP_INT *)(alloc_ptr+1);
|
||||
/* first reserve space for the functor */
|
||||
alloc_ptr[0] = 0L;
|
||||
/* now allocate space for mpz_t */
|
||||
alloc_ptr = (CELL *)(ret+1);
|
||||
/* initialise the fields */
|
||||
mpz_init(ret);
|
||||
return(ret);
|
||||
}
|
||||
|
||||
void
|
||||
Yap_CleanBigNum(void)
|
||||
{
|
||||
H = pre_alloc_base;
|
||||
pre_alloc_base = NULL;
|
||||
}
|
||||
|
||||
MP_INT *
|
||||
Yap_InitBigNum(Int in)
|
||||
{
|
||||
MP_INT *ret;
|
||||
|
||||
if (pre_alloc_base == NULL) {
|
||||
/* inform where we are allocating */
|
||||
alloc_ptr = pre_alloc_base = H;
|
||||
}
|
||||
ret = (MP_INT *)(alloc_ptr+1);
|
||||
/* first reserve space for the functor */
|
||||
/* I use a 0 to indicate this is the first time
|
||||
we are building the bignum */
|
||||
alloc_ptr[0] = 0L;
|
||||
/* now allocate space for mpz_t */
|
||||
alloc_ptr = (CELL *)(ret+1);
|
||||
/* initialise the fields */
|
||||
mpz_init_set_si(ret, in);
|
||||
return(ret);
|
||||
}
|
||||
|
||||
/* This can be done in several different situations:
|
||||
- we did BigIntOf and want to recover now (check through ret[0]);
|
||||
- we have done PreAlloc() and then a lot happened in between:
|
||||
o our final computation fits in an Int;
|
||||
o our final computation is the first we PreAlloced();
|
||||
o our final computation is not the first term we PreAlloced();
|
||||
|
||||
The result may be an Int, the old BigInt, or a BigInt moved to
|
||||
pre_alloc_base;
|
||||
*/
|
||||
Term
|
||||
Yap_MkBigIntTerm(MP_INT *big)
|
||||
{
|
||||
CELL *new = (CELL *)(big+1);
|
||||
Int nlimbs = (big->_mp_alloc)*(sizeof(mp_limb_t)/CellSize);
|
||||
Int sz;
|
||||
CELL *ret = ((CELL *)big)-1;
|
||||
int sz0 = mpz_sizeinbase(big, 2);
|
||||
Int nlimbs;
|
||||
MP_INT *dst = (MP_INT *)(H+1);
|
||||
CELL *ret = H;
|
||||
|
||||
sz = mpz_sizeinbase(big, 2);
|
||||
/* was already there */
|
||||
if (ret[0] == (CELL)FunctorBigInt) {
|
||||
/* don't need to do no nothing */
|
||||
return(AbsAppl(ret));
|
||||
if (sz0 < SIZEOF_LONG_INT*8-1) {
|
||||
int out = mpz_get_si(big);
|
||||
mpz_clear(big);
|
||||
return MkIntegerTerm(out);
|
||||
}
|
||||
if (sz < SIZEOF_LONG_INT*8-1) {
|
||||
Int out;
|
||||
|
||||
H = pre_alloc_base;
|
||||
pre_alloc_base = NULL;
|
||||
out = mpz_get_si(big);
|
||||
return(MkIntegerTerm(out));
|
||||
} else {
|
||||
/* we may have created a lot of bignums since we did the first
|
||||
PreAlloc(). We want to recover the space, not leave "holes" on
|
||||
the global stack */
|
||||
if (pre_alloc_base != ret) {
|
||||
/* copy everything to the start of the temp area */
|
||||
MP_INT *dst = (MP_INT *)(pre_alloc_base+1);
|
||||
nlimbs = (big->_mp_alloc)*(sizeof(mp_limb_t)/CellSize);
|
||||
if (nlimbs > (ASP-ret)-1024) {
|
||||
mpz_clear(big);
|
||||
return TermNil;
|
||||
}
|
||||
H[0] = (CELL)FunctorBigInt;
|
||||
|
||||
dst->_mp_size = big->_mp_size;
|
||||
dst->_mp_alloc = big->_mp_alloc;
|
||||
new = (CELL *)(dst+1);
|
||||
ret = pre_alloc_base;
|
||||
}
|
||||
ret[0] = (CELL)FunctorBigInt;
|
||||
memmove((void *)new, (const void *)(big->_mp_d), nlimbs*CellSize);
|
||||
H = (CELL *)(new+nlimbs);
|
||||
if ((char *)H-(char *)ret > MAX_SPECIALS_TAG-EndSpecials) {
|
||||
/* too large */
|
||||
return TermNil;
|
||||
}
|
||||
dst->_mp_size = big->_mp_size;
|
||||
dst->_mp_alloc = big->_mp_alloc;
|
||||
memmove((void *)(dst+1), (const void *)(big->_mp_d), nlimbs*CellSize);
|
||||
H = (CELL *)(dst+1)+nlimbs;
|
||||
if ((char *)H-(char *)ret > MAX_SPECIALS_TAG-EndSpecials) {
|
||||
/* too large */
|
||||
mpz_clear(big);
|
||||
return TermNil;
|
||||
}
|
||||
#if GC_NO_TAGS
|
||||
H[0] = (H-ret)*sizeof(CELL)+EndSpecials;
|
||||
H[0] = (H-ret)*sizeof(CELL)+EndSpecials;
|
||||
#else
|
||||
H[0] = ((H-ret)*sizeof(CELL)+EndSpecials)|MBIT;
|
||||
H[0] = ((H-ret)*sizeof(CELL)+EndSpecials)|MBIT;
|
||||
#endif
|
||||
H++;
|
||||
pre_alloc_base = NULL;
|
||||
return(AbsAppl(ret));
|
||||
}
|
||||
H++;
|
||||
mpz_clear(big);
|
||||
return AbsAppl(ret);
|
||||
}
|
||||
|
||||
MP_INT *
|
||||
@@ -223,8 +84,9 @@ Term
|
||||
Yap_MkULLIntTerm(YAP_ULONG_LONG n)
|
||||
{
|
||||
#if __GNUC__ && USE_GMP
|
||||
MP_INT *new = Yap_PreAllocBigNum();
|
||||
mpz_t new;
|
||||
char tmp[256];
|
||||
Term t;
|
||||
|
||||
#if HAVE_SNPRINTF
|
||||
snprintf(tmp,256,"%llu",n);
|
||||
@@ -232,12 +94,13 @@ Yap_MkULLIntTerm(YAP_ULONG_LONG n)
|
||||
sprintf(tmp,"%llu",n);
|
||||
#endif
|
||||
/* try to scan it as a bignum */
|
||||
mpz_init(new);
|
||||
mpz_set_str(new, tmp, 10);
|
||||
mpz_init_set_str (new, tmp, 10);
|
||||
if (mpz_fits_slong_p(new)) {
|
||||
return MkIntegerTerm(mpz_get_si(new));
|
||||
}
|
||||
return Yap_MkBigIntTerm(new);
|
||||
t = Yap_MkBigIntTerm(new);
|
||||
mpz_clear(new);
|
||||
return t;
|
||||
#else
|
||||
return MkIntegerTerm(n);
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user