support for rational numbers
make floor and friends return an integer (make it closer to SICStus).
This commit is contained in:
179
C/arith1.c
179
C/arith1.c
@@ -37,9 +37,7 @@ float_to_int(Float v)
|
||||
if (i-v == 0.0) {
|
||||
return MkIntegerTerm(i);
|
||||
} else {
|
||||
MP_INT o;
|
||||
mpz_init_set_d(&o, v);
|
||||
return Yap_MkBigIntTerm(&o);
|
||||
return Yap_gmp_float_to_big(v);
|
||||
}
|
||||
#else
|
||||
return MkIntegerTerm(v);
|
||||
@@ -48,24 +46,6 @@ float_to_int(Float v)
|
||||
|
||||
#define RBIG_FL(v) return(float_to_int(v))
|
||||
|
||||
#if USE_GMP
|
||||
static Term
|
||||
process_iso_error(MP_INT *big, Term t, char *operation)
|
||||
{ /* iso */
|
||||
Int sz = 2+mpz_sizeinbase(big,10);
|
||||
char *s = Yap_AllocCodeSpace(sz);
|
||||
|
||||
if (s != NULL) {
|
||||
mpz_get_str(s, 10, big);
|
||||
Yap_ArithError(TYPE_ERROR_FLOAT, t, "X is %s(%s)", operation, s);
|
||||
Yap_FreeCodeSpace(s);
|
||||
RERROR();
|
||||
} else {
|
||||
return Yap_ArithError(TYPE_ERROR_FLOAT, t, "X is %s(t)",operation);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
typedef struct init_un_eval {
|
||||
char *OpName;
|
||||
arith1_op f;
|
||||
@@ -104,7 +84,7 @@ get_float(Term t) {
|
||||
}
|
||||
#ifdef USE_GMP
|
||||
if (IsBigIntTerm(t)) {
|
||||
return mpz_get_d(Yap_BigIntOfTerm(t));
|
||||
return Yap_gmp_to_float(t);
|
||||
}
|
||||
#endif
|
||||
return 0.0;
|
||||
@@ -434,33 +414,13 @@ eval1(Int fi, Term t) {
|
||||
|
||||
switch (ETypeOfTerm(t)) {
|
||||
case long_int_e:
|
||||
if (yap_flags[LANGUAGE_MODE_FLAG] == 1) { /* iso */
|
||||
return Yap_ArithError(TYPE_ERROR_FLOAT, t, "X is floor(%f)", IntegerOfTerm(t));
|
||||
} else {
|
||||
RFLOAT(IntegerOfTerm(t));
|
||||
}
|
||||
return t;
|
||||
case double_e:
|
||||
dbl = FloatOfTerm(t);
|
||||
break;
|
||||
case big_int_e:
|
||||
#ifdef USE_GMP
|
||||
if (yap_flags[LANGUAGE_MODE_FLAG] == 1) { /* iso */
|
||||
MP_INT *big = Yap_BigIntOfTerm(t);
|
||||
Int sz = 2+mpz_sizeinbase(big,10);
|
||||
char *s = Yap_AllocCodeSpace(sz);
|
||||
|
||||
if (s != NULL) {
|
||||
mpz_get_str(s, 10, big);
|
||||
Yap_ArithError(TYPE_ERROR_FLOAT, t, "X is floor(%s)", s);
|
||||
Yap_FreeCodeSpace(s);
|
||||
RERROR();
|
||||
} else {
|
||||
return Yap_ArithError(TYPE_ERROR_FLOAT, t, "X is floor(t)");
|
||||
}
|
||||
} else {
|
||||
dbl = mpz_get_d(Yap_BigIntOfTerm(t));
|
||||
}
|
||||
break;
|
||||
return Yap_gmp_floor(t);
|
||||
#endif
|
||||
default:
|
||||
RERROR();
|
||||
@@ -483,22 +443,13 @@ eval1(Int fi, Term t) {
|
||||
Float dbl;
|
||||
switch (ETypeOfTerm(t)) {
|
||||
case long_int_e:
|
||||
if (yap_flags[LANGUAGE_MODE_FLAG] == 1) { /* iso */
|
||||
return Yap_ArithError(TYPE_ERROR_FLOAT, t, "X is ceiling(%f)", IntegerOfTerm(t));
|
||||
} else {
|
||||
RFLOAT(IntegerOfTerm(t));
|
||||
}
|
||||
return t;
|
||||
case double_e:
|
||||
dbl = FloatOfTerm(t);
|
||||
break;
|
||||
case big_int_e:
|
||||
#ifdef USE_GMP
|
||||
if (yap_flags[LANGUAGE_MODE_FLAG] == 1) { /* iso */
|
||||
return process_iso_error(Yap_BigIntOfTerm(t), t, "ceiling");
|
||||
} else {
|
||||
dbl = mpz_get_d(Yap_BigIntOfTerm(t));
|
||||
}
|
||||
break;
|
||||
return Yap_gmp_ceiling(t);
|
||||
#endif
|
||||
default:
|
||||
RERROR();
|
||||
@@ -522,21 +473,13 @@ eval1(Int fi, Term t) {
|
||||
|
||||
switch (ETypeOfTerm(t)) {
|
||||
case long_int_e:
|
||||
if (yap_flags[LANGUAGE_MODE_FLAG] == 1) { /* iso */
|
||||
return Yap_ArithError(TYPE_ERROR_FLOAT, t, "X is round(%ld)", IntegerOfTerm(t));
|
||||
} else {
|
||||
return t;
|
||||
}
|
||||
return t;
|
||||
case double_e:
|
||||
dbl = FloatOfTerm(t);
|
||||
break;
|
||||
case big_int_e:
|
||||
#ifdef USE_GMP
|
||||
if (yap_flags[LANGUAGE_MODE_FLAG] == 1) {
|
||||
return process_iso_error(Yap_BigIntOfTerm(t), t, "round");
|
||||
}
|
||||
return t;
|
||||
break;
|
||||
return Yap_gmp_round(t);
|
||||
#endif
|
||||
default:
|
||||
RERROR();
|
||||
@@ -560,19 +503,13 @@ eval1(Int fi, Term t) {
|
||||
Float dbl;
|
||||
switch (ETypeOfTerm(t)) {
|
||||
case long_int_e:
|
||||
if (yap_flags[LANGUAGE_MODE_FLAG] == 1) { /* iso */
|
||||
return Yap_ArithError(TYPE_ERROR_FLOAT, t, "X is round(%ld)", IntegerOfTerm(t));
|
||||
}
|
||||
return t;
|
||||
case double_e:
|
||||
dbl = FloatOfTerm(t);
|
||||
break;
|
||||
case big_int_e:
|
||||
#ifdef USE_GMP
|
||||
if (yap_flags[LANGUAGE_MODE_FLAG] == 1) { /* iso */
|
||||
return Yap_ArithError(TYPE_ERROR_FLOAT, t, "X is round(BIGNUM)");
|
||||
}
|
||||
return t;
|
||||
return Yap_gmp_trunc(t);
|
||||
#endif
|
||||
default:
|
||||
RERROR();
|
||||
@@ -588,18 +525,10 @@ eval1(Int fi, Term t) {
|
||||
(%f)",dbl);
|
||||
}
|
||||
#endif
|
||||
if (dbl <= (Float)Int_MAX && dbl >= (Float)Int_MIN) {
|
||||
RINT((Int) dbl);
|
||||
} else {
|
||||
#ifdef USE_GMP
|
||||
MP_INT new;
|
||||
|
||||
mpz_init_set_d(&new, dbl);
|
||||
RBIG(&new);
|
||||
#else
|
||||
return Yap_ArithError(EVALUATION_ERROR_INT_OVERFLOW, MkFloatTerm(dbl), "integer/1");
|
||||
#endif
|
||||
}
|
||||
if (dbl < 0.0)
|
||||
RBIG_FL(ceil(dbl));
|
||||
else
|
||||
RBIG_FL(floor(dbl));
|
||||
}
|
||||
case op_float:
|
||||
switch (ETypeOfTerm(t)) {
|
||||
@@ -609,11 +538,37 @@ eval1(Int fi, Term t) {
|
||||
return t;
|
||||
case big_int_e:
|
||||
#ifdef USE_GMP
|
||||
RFLOAT(mpz_get_d(Yap_BigIntOfTerm(t)));
|
||||
RFLOAT(Yap_gmp_to_float(t));
|
||||
#endif
|
||||
default:
|
||||
RERROR();
|
||||
}
|
||||
case op_rational:
|
||||
switch (ETypeOfTerm(t)) {
|
||||
case long_int_e:
|
||||
return t;
|
||||
#ifdef USE_GMP
|
||||
case double_e:
|
||||
return Yap_gmp_float_to_rational(FloatOfTerm(t));
|
||||
#endif
|
||||
case big_int_e:
|
||||
return t;
|
||||
default:
|
||||
RERROR();
|
||||
}
|
||||
case op_rationalize:
|
||||
switch (ETypeOfTerm(t)) {
|
||||
case long_int_e:
|
||||
return t;
|
||||
#ifdef USE_GMP
|
||||
case double_e:
|
||||
return Yap_gmp_float_rationalize(FloatOfTerm(t));
|
||||
#endif
|
||||
case big_int_e:
|
||||
return t;
|
||||
default:
|
||||
RERROR();
|
||||
}
|
||||
case op_abs:
|
||||
switch (ETypeOfTerm(t)) {
|
||||
case long_int_e:
|
||||
@@ -622,13 +577,7 @@ eval1(Int fi, Term t) {
|
||||
RFLOAT(fabs(FloatOfTerm(t)));
|
||||
case big_int_e:
|
||||
#ifdef USE_GMP
|
||||
{
|
||||
MP_INT new;
|
||||
|
||||
mpz_init_set(&new, Yap_BigIntOfTerm(t));
|
||||
mpz_abs(&new, &new);
|
||||
RBIG(&new);
|
||||
}
|
||||
return Yap_gmp_abs_big(t);
|
||||
#endif
|
||||
default:
|
||||
RERROR();
|
||||
@@ -641,13 +590,7 @@ eval1(Int fi, Term t) {
|
||||
return Yap_ArithError(TYPE_ERROR_INTEGER, t, "msb(%f)", FloatOfTerm(t));
|
||||
case big_int_e:
|
||||
#ifdef USE_GMP
|
||||
{ MP_INT *big = Yap_BigIntOfTerm(t);
|
||||
if ( mpz_sgn(big) <= 0 ) {
|
||||
return Yap_ArithError(DOMAIN_ERROR_NOT_LESS_THAN_ZERO, t,
|
||||
"msb/1 received bignum");
|
||||
}
|
||||
RINT(mpz_sizeinbase(big,2));
|
||||
}
|
||||
return Yap_gmp_msb(t);
|
||||
#endif
|
||||
default:
|
||||
RERROR();
|
||||
@@ -660,13 +603,7 @@ eval1(Int fi, Term t) {
|
||||
return Yap_ArithError(TYPE_ERROR_INTEGER, t, "lsb(%f)", FloatOfTerm(t));
|
||||
case big_int_e:
|
||||
#ifdef USE_GMP
|
||||
{ MP_INT *big = Yap_BigIntOfTerm(t);
|
||||
if ( mpz_sgn(big) <= 0 ) {
|
||||
return Yap_ArithError(DOMAIN_ERROR_NOT_LESS_THAN_ZERO, t,
|
||||
"lsb/1 received bignum");
|
||||
}
|
||||
RINT(mpz_scan1(big,0));
|
||||
}
|
||||
return Yap_gmp_lsb(t);
|
||||
#endif
|
||||
default:
|
||||
RERROR();
|
||||
@@ -679,13 +616,7 @@ eval1(Int fi, Term t) {
|
||||
return Yap_ArithError(TYPE_ERROR_INTEGER, t, "popcount(%f)", FloatOfTerm(t));
|
||||
case big_int_e:
|
||||
#ifdef USE_GMP
|
||||
{ MP_INT *big = Yap_BigIntOfTerm(t);
|
||||
if ( mpz_sgn(big) <= 0 ) {
|
||||
return Yap_ArithError(DOMAIN_ERROR_NOT_LESS_THAN_ZERO, t,
|
||||
"popcount/1 received negative bignum");
|
||||
}
|
||||
RINT(mpz_popcount(big));
|
||||
}
|
||||
return Yap_gmp_popcount(t);
|
||||
#endif
|
||||
default:
|
||||
RERROR();
|
||||
@@ -707,11 +638,7 @@ eval1(Int fi, Term t) {
|
||||
break;
|
||||
case big_int_e:
|
||||
#ifdef USE_GMP
|
||||
if (yap_flags[LANGUAGE_MODE_FLAG] == 1) { /* iso */
|
||||
return process_iso_error(Yap_BigIntOfTerm(t), t, "float_fractional_part");
|
||||
} else {
|
||||
RFLOAT(0.0);
|
||||
}
|
||||
return Yap_gmp_float_fractional_part(t);
|
||||
#endif
|
||||
default:
|
||||
RERROR();
|
||||
@@ -719,21 +646,13 @@ eval1(Int fi, Term t) {
|
||||
case op_fintp:
|
||||
switch (ETypeOfTerm(t)) {
|
||||
case long_int_e:
|
||||
if (yap_flags[LANGUAGE_MODE_FLAG] == 1) { /* iso */
|
||||
return Yap_ArithError(TYPE_ERROR_FLOAT, t, "X is float_integer_part(%f)", IntegerOfTerm(t));
|
||||
} else {
|
||||
RFLOAT(IntegerOfTerm(t));
|
||||
}
|
||||
return Yap_ArithError(TYPE_ERROR_FLOAT, t, "X is float_integer_part(%f)", IntegerOfTerm(t));
|
||||
case double_e:
|
||||
RFLOAT(rint(FloatOfTerm(t)));
|
||||
break;
|
||||
case big_int_e:
|
||||
#ifdef USE_GMP
|
||||
if (yap_flags[LANGUAGE_MODE_FLAG] == 1) { /* iso */
|
||||
return process_iso_error(Yap_BigIntOfTerm(t), t, "float_integer_part");
|
||||
} else {
|
||||
RFLOAT(mpz_get_d(Yap_BigIntOfTerm(t)));
|
||||
}
|
||||
return Yap_gmp_float_integer_part(t);
|
||||
#endif
|
||||
default:
|
||||
RERROR();
|
||||
@@ -755,7 +674,7 @@ eval1(Int fi, Term t) {
|
||||
}
|
||||
case big_int_e:
|
||||
#ifdef USE_GMP
|
||||
RINT(mpz_sgn(Yap_BigIntOfTerm(t)));
|
||||
return Yap_gmp_sign(t);
|
||||
#endif
|
||||
default:
|
||||
RERROR();
|
||||
@@ -818,6 +737,8 @@ static InitUnEntry InitUnTab[] = {
|
||||
{"lgamma", op_lgamma},
|
||||
{"erf",op_erf},
|
||||
{"erfc",op_erfc},
|
||||
{"rational",op_rational},
|
||||
{"rationalize",op_rationalize},
|
||||
{"random", op_random1}
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user