2001-04-09 20:54:03 +01:00
|
|
|
/*************************************************************************
|
|
|
|
* *
|
|
|
|
* YAP Prolog *
|
|
|
|
* *
|
|
|
|
* Yap Prolog was developed at NCCUP - Universidade do Porto *
|
|
|
|
* *
|
|
|
|
* Copyright L.Damas, V.S.Costa and Universidade do Porto 1985-1997 *
|
|
|
|
* *
|
|
|
|
**************************************************************************
|
|
|
|
* *
|
|
|
|
* File: arith1.c *
|
|
|
|
* Last rev: *
|
|
|
|
* mods: *
|
|
|
|
* comments: bignum support through gmp *
|
|
|
|
* *
|
|
|
|
*************************************************************************/
|
|
|
|
#ifdef SCCS
|
|
|
|
static char SccsId[] = "%W% %G%";
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include "Yap.h"
|
|
|
|
#include "Yatom.h"
|
|
|
|
|
|
|
|
#ifdef USE_GMP
|
|
|
|
|
|
|
|
#include "Heap.h"
|
|
|
|
#include "eval.h"
|
|
|
|
#include "alloc.h"
|
|
|
|
#if HAVE_STRING_H
|
|
|
|
#include <string.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
Term
|
2002-11-18 18:18:05 +00:00
|
|
|
Yap_MkBigIntTerm(MP_INT *big)
|
2001-04-09 20:54:03 +01:00
|
|
|
{
|
2006-01-02 02:16:19 +00:00
|
|
|
Int nlimbs;
|
|
|
|
MP_INT *dst = (MP_INT *)(H+1);
|
|
|
|
CELL *ret = H;
|
|
|
|
|
2006-01-16 02:57:52 +00:00
|
|
|
if (mpz_fits_slong_p(big)) {
|
2006-02-01 13:28:57 +00:00
|
|
|
long int out = mpz_get_si(big);
|
|
|
|
return MkIntegerTerm((Int)out);
|
2006-01-02 02:25:45 +00:00
|
|
|
}
|
|
|
|
nlimbs = (big->_mp_alloc)*(sizeof(mp_limb_t)/CellSize);
|
|
|
|
if (nlimbs > (ASP-ret)-1024) {
|
|
|
|
return TermNil;
|
|
|
|
}
|
|
|
|
H[0] = (CELL)FunctorBigInt;
|
|
|
|
|
|
|
|
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 */
|
|
|
|
return TermNil;
|
|
|
|
}
|
|
|
|
#if GC_NO_TAGS
|
|
|
|
H[0] = (H-ret)*sizeof(CELL)+EndSpecials;
|
|
|
|
#else
|
|
|
|
H[0] = ((H-ret)*sizeof(CELL)+EndSpecials)|MBIT;
|
|
|
|
#endif
|
|
|
|
H++;
|
|
|
|
return AbsAppl(ret);
|
|
|
|
}
|
|
|
|
|
2001-04-09 20:54:03 +01:00
|
|
|
MP_INT *
|
2002-11-18 18:18:05 +00:00
|
|
|
Yap_BigIntOfTerm(Term t)
|
2001-04-09 20:54:03 +01:00
|
|
|
{
|
|
|
|
MP_INT *new = (MP_INT *)(RepAppl(t)+1);
|
|
|
|
|
|
|
|
new->_mp_d = (mp_limb_t *)(new+1);
|
|
|
|
return(new);
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
2003-03-20 15:10:18 +00:00
|
|
|
Term
|
|
|
|
Yap_MkULLIntTerm(YAP_ULONG_LONG n)
|
|
|
|
{
|
2005-11-16 02:01:09 +00:00
|
|
|
#if __GNUC__ && USE_GMP
|
2006-01-02 02:16:19 +00:00
|
|
|
mpz_t new;
|
2005-11-15 02:05:49 +00:00
|
|
|
char tmp[256];
|
2006-01-02 02:16:19 +00:00
|
|
|
Term t;
|
2005-11-15 02:05:49 +00:00
|
|
|
|
|
|
|
#if HAVE_SNPRINTF
|
2005-11-16 01:55:03 +00:00
|
|
|
snprintf(tmp,256,"%llu",n);
|
2005-11-15 02:05:49 +00:00
|
|
|
#else
|
|
|
|
sprintf(tmp,"%llu",n);
|
|
|
|
#endif
|
|
|
|
/* try to scan it as a bignum */
|
2006-01-02 02:16:19 +00:00
|
|
|
mpz_init_set_str (new, tmp, 10);
|
2005-11-15 02:05:49 +00:00
|
|
|
if (mpz_fits_slong_p(new)) {
|
|
|
|
return MkIntegerTerm(mpz_get_si(new));
|
|
|
|
}
|
2006-01-02 02:16:19 +00:00
|
|
|
t = Yap_MkBigIntTerm(new);
|
2006-01-18 15:34:54 +00:00
|
|
|
mpz_clear(new);
|
2006-01-02 02:16:19 +00:00
|
|
|
return t;
|
2003-03-20 15:10:18 +00:00
|
|
|
#else
|
|
|
|
return MkIntegerTerm(n);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2001-04-09 20:54:03 +01:00
|
|
|
static Int
|
|
|
|
p_is_bignum(void)
|
|
|
|
{
|
|
|
|
#ifdef USE_GMP
|
|
|
|
Term t = Deref(ARG1);
|
|
|
|
return(IsNonVarTerm(t) && IsApplTerm(t) && FunctorOfTerm(t) == FunctorBigInt);
|
|
|
|
#else
|
|
|
|
return(FALSE);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2002-11-18 18:18:05 +00:00
|
|
|
Yap_InitBigNums(void)
|
2001-04-09 20:54:03 +01:00
|
|
|
{
|
2004-11-18 22:32:40 +00:00
|
|
|
Yap_InitCPred("$bignum", 1, p_is_bignum, SafePredFlag|HiddenPredFlag);
|
2001-04-09 20:54:03 +01:00
|
|
|
}
|