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: eval.c *
|
|
|
|
* Last rev: *
|
|
|
|
* mods: *
|
|
|
|
* comments: arithmetical expression evaluation *
|
|
|
|
* *
|
|
|
|
*************************************************************************/
|
|
|
|
#ifdef SCCS
|
|
|
|
static char SccsId[] = "%W% %G%";
|
|
|
|
#endif
|
|
|
|
|
2015-01-04 23:58:23 +00:00
|
|
|
//! @file eval.c
|
|
|
|
|
|
|
|
//! @{
|
2014-04-21 11:14:18 +01:00
|
|
|
|
2015-01-04 23:58:23 +00:00
|
|
|
/**
|
2014-04-21 11:14:18 +01:00
|
|
|
@defgroup arithmetic_preds Arithmetic Predicates
|
|
|
|
@ingroup arithmetic
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
2001-04-09 20:54:03 +01:00
|
|
|
#include "Yap.h"
|
|
|
|
#include "Yatom.h"
|
2009-10-23 14:22:17 +01:00
|
|
|
#include "YapHeap.h"
|
2001-04-09 20:54:03 +01:00
|
|
|
#include "eval.h"
|
2009-05-22 20:44:32 +01:00
|
|
|
#if HAVE_STDARG_H
|
|
|
|
#include <stdarg.h>
|
|
|
|
#endif
|
|
|
|
#include <stdlib.h>
|
|
|
|
#if HAVE_UNISTD_H
|
|
|
|
#include <unistd.h>
|
|
|
|
#endif
|
2014-10-14 15:53:24 +01:00
|
|
|
#if HAVE_FENV_H
|
|
|
|
#include <fenv.h>
|
|
|
|
#endif
|
2001-04-09 20:54:03 +01:00
|
|
|
|
2011-10-27 11:36:48 +01:00
|
|
|
static Term Eval(Term t1 USES_REGS);
|
2011-05-25 16:40:36 +01:00
|
|
|
|
2011-10-27 11:36:48 +01:00
|
|
|
static Term
|
|
|
|
get_matrix_element(Term t1, Term t2 USES_REGS)
|
|
|
|
{
|
|
|
|
if (!IsPairTerm(t2)) {
|
|
|
|
if (t2 == MkAtomTerm(AtomLength)) {
|
|
|
|
Int sz = 1;
|
|
|
|
while (IsApplTerm(t1)) {
|
|
|
|
Functor f = FunctorOfTerm(t1);
|
|
|
|
if (NameOfFunctor(f) != AtomNil) {
|
|
|
|
return MkIntegerTerm(sz);
|
|
|
|
}
|
|
|
|
sz *= ArityOfFunctor(f);
|
|
|
|
t1 = ArgOfTerm(1, t1);
|
|
|
|
}
|
|
|
|
return MkIntegerTerm(sz);
|
|
|
|
}
|
|
|
|
Yap_ArithError(TYPE_ERROR_EVALUABLE, t2, "X is Y^[A]");
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
while (IsPairTerm(t2)) {
|
|
|
|
Int indx;
|
|
|
|
Term indxt = Eval(HeadOfTerm(t2) PASS_REGS);
|
|
|
|
if (!IsIntegerTerm(indxt)) {
|
|
|
|
Yap_ArithError(TYPE_ERROR_EVALUABLE, t2, "X is Y^[A]");
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
indx = IntegerOfTerm(indxt);
|
|
|
|
if (!IsApplTerm(t1)) {
|
|
|
|
Yap_ArithError(TYPE_ERROR_EVALUABLE, t1, "X is Y^[A]");
|
|
|
|
return FALSE;
|
|
|
|
} else {
|
|
|
|
Functor f = FunctorOfTerm(t1);
|
|
|
|
if (ArityOfFunctor(f) < indx) {
|
|
|
|
Yap_ArithError(TYPE_ERROR_EVALUABLE, t1, "X is Y^[A]");
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
t1 = ArgOfTerm(indx, t1);
|
|
|
|
t2 = TailOfTerm(t2);
|
|
|
|
}
|
|
|
|
if (t2 != TermNil) {
|
|
|
|
Yap_ArithError(TYPE_ERROR_EVALUABLE, t2, "X is Y^[A]");
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
return Eval(t1 PASS_REGS);
|
|
|
|
}
|
2001-04-09 20:54:03 +01:00
|
|
|
|
|
|
|
static Term
|
2011-03-07 16:02:55 +00:00
|
|
|
Eval(Term t USES_REGS)
|
2001-04-09 20:54:03 +01:00
|
|
|
{
|
2014-10-14 15:53:24 +01:00
|
|
|
|
2001-04-09 20:54:03 +01:00
|
|
|
if (IsVarTerm(t)) {
|
2009-05-22 17:21:39 +01:00
|
|
|
return Yap_ArithError(INSTANTIATION_ERROR,t,"in arithmetic");
|
2010-01-11 10:35:36 +00:00
|
|
|
} else if (IsNumTerm(t)) {
|
|
|
|
return t;
|
2008-12-04 23:33:32 +00:00
|
|
|
} else if (IsAtomTerm(t)) {
|
2002-11-11 17:38:10 +00:00
|
|
|
ExpEntry *p;
|
2008-12-04 23:33:32 +00:00
|
|
|
Atom name = AtomOfTerm(t);
|
2002-11-11 17:38:10 +00:00
|
|
|
|
2002-11-18 18:18:05 +00:00
|
|
|
if (EndOfPAEntr(p = RepExpProp(Yap_GetExpProp(name, 0)))) {
|
2007-06-04 13:28:02 +01:00
|
|
|
/* error */
|
2014-10-16 10:49:11 +01:00
|
|
|
Term ti[2];
|
|
|
|
|
|
|
|
/* error */
|
|
|
|
ti[0] = t;
|
|
|
|
ti[1] = MkIntTerm(0);
|
|
|
|
t = Yap_MkApplTerm(FunctorSlash, 2, ti);
|
|
|
|
|
2010-02-26 12:01:08 +00:00
|
|
|
return Yap_ArithError(TYPE_ERROR_EVALUABLE, t,
|
2014-10-16 10:49:11 +01:00
|
|
|
"atom %s in arithmetic expression",
|
2009-05-22 17:24:44 +01:00
|
|
|
RepAtom(name)->StrOfAE);
|
2002-11-11 17:38:10 +00:00
|
|
|
}
|
2008-12-04 23:33:32 +00:00
|
|
|
return Yap_eval_atom(p->FOfEE);
|
|
|
|
} else if (IsApplTerm(t)) {
|
2001-04-09 20:54:03 +01:00
|
|
|
Functor fun = FunctorOfTerm(t);
|
2014-03-12 15:47:53 +00:00
|
|
|
if (fun == FunctorString) {
|
|
|
|
const char *s = StringOfTerm(t);
|
|
|
|
if (s[1] == '\0')
|
|
|
|
return MkIntegerTerm(s[0]);
|
|
|
|
return Yap_ArithError(TYPE_ERROR_EVALUABLE, t,
|
|
|
|
"string in arithmetic expression");
|
|
|
|
} else if ((Atom)fun == AtomFoundVar) {
|
2010-01-11 10:35:36 +00:00
|
|
|
return Yap_ArithError(TYPE_ERROR_EVALUABLE, TermNil,
|
|
|
|
"cyclic term in arithmetic expression");
|
|
|
|
} else {
|
|
|
|
Int n = ArityOfFunctor(fun);
|
|
|
|
Atom name = NameOfFunctor(fun);
|
|
|
|
ExpEntry *p;
|
|
|
|
Term t1, t2;
|
|
|
|
|
|
|
|
if (EndOfPAEntr(p = RepExpProp(Yap_GetExpProp(name, n)))) {
|
|
|
|
Term ti[2];
|
2009-05-22 17:21:39 +01:00
|
|
|
|
2010-01-11 10:35:36 +00:00
|
|
|
/* error */
|
|
|
|
ti[0] = t;
|
|
|
|
ti[1] = MkIntegerTerm(n);
|
|
|
|
t = Yap_MkApplTerm(FunctorSlash, 2, ti);
|
|
|
|
return Yap_ArithError(TYPE_ERROR_EVALUABLE, t,
|
|
|
|
"functor %s/%d for arithmetic expression",
|
|
|
|
RepAtom(name)->StrOfAE,n);
|
|
|
|
}
|
2011-10-27 11:36:48 +01:00
|
|
|
if (p->FOfEE == op_power && p->ArityOfEE == 2) {
|
|
|
|
t2 = ArgOfTerm(2, t);
|
|
|
|
if (IsPairTerm(t2)) {
|
|
|
|
return get_matrix_element(ArgOfTerm(1, t), t2 PASS_REGS);
|
|
|
|
}
|
|
|
|
}
|
2010-01-11 10:35:36 +00:00
|
|
|
*RepAppl(t) = (CELL)AtomFoundVar;
|
2011-03-07 16:02:55 +00:00
|
|
|
t1 = Eval(ArgOfTerm(1,t) PASS_REGS);
|
2010-01-11 10:35:36 +00:00
|
|
|
if (t1 == 0L) {
|
|
|
|
*RepAppl(t) = (CELL)fun;
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
if (n == 1) {
|
|
|
|
*RepAppl(t) = (CELL)fun;
|
|
|
|
return Yap_eval_unary(p->FOfEE, t1);
|
2001-04-09 20:54:03 +01:00
|
|
|
}
|
2011-03-07 16:02:55 +00:00
|
|
|
t2 = Eval(ArgOfTerm(2,t) PASS_REGS);
|
2010-01-11 10:35:36 +00:00
|
|
|
*RepAppl(t) = (CELL)fun;
|
|
|
|
if (t2 == 0L)
|
|
|
|
return FALSE;
|
|
|
|
return Yap_eval_binary(p->FOfEE,t1,t2);
|
2001-04-09 20:54:03 +01:00
|
|
|
}
|
2008-12-04 23:33:32 +00:00
|
|
|
} /* else if (IsPairTerm(t)) */ {
|
2008-04-08 16:36:53 +01:00
|
|
|
if (TailOfTerm(t) != TermNil) {
|
2009-05-22 17:24:44 +01:00
|
|
|
return Yap_ArithError(TYPE_ERROR_EVALUABLE, t,
|
|
|
|
"string must contain a single character to be evaluated as an arithmetic expression");
|
2001-04-09 20:54:03 +01:00
|
|
|
}
|
2011-03-07 16:02:55 +00:00
|
|
|
return Eval(HeadOfTerm(t) PASS_REGS);
|
2001-04-09 20:54:03 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-10-14 15:53:24 +01:00
|
|
|
Term
|
|
|
|
Yap_InnerEval__(Term t USES_REGS)
|
|
|
|
{
|
2011-03-07 16:02:55 +00:00
|
|
|
return Eval(t PASS_REGS);
|
2008-12-04 23:33:32 +00:00
|
|
|
}
|
|
|
|
|
2005-09-08 23:06:45 +01:00
|
|
|
#ifdef BEAM
|
|
|
|
Int BEAM_is(void);
|
|
|
|
|
|
|
|
Int
|
|
|
|
BEAM_is(void)
|
|
|
|
{ /* X is Y */
|
|
|
|
union arith_ret res;
|
|
|
|
blob_type bt;
|
|
|
|
|
|
|
|
bt = Eval(Deref(XREGS[2]), &res);
|
|
|
|
if (bt==db_ref_e) return (NULL);
|
|
|
|
return (EvalToTerm(bt,&res));
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
2014-04-21 11:14:18 +01:00
|
|
|
/**
|
2014-05-14 10:01:11 +01:00
|
|
|
@pred is( X:number, + Y:ground) is det
|
2014-04-21 11:14:18 +01:00
|
|
|
|
|
|
|
This predicate succeeds iff the result of evaluating the expression
|
|
|
|
_Y_ unifies with _X_. This is the predicate normally used to
|
|
|
|
perform evaluation of arithmetic expressions:
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
X is 2+3*4
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
succeeds with `X = 14`.
|
|
|
|
|
2014-09-15 09:13:50 +01:00
|
|
|
Consult @ref arithmetic_operators for the complete list of arithmetic_operators
|
|
|
|
|
2014-04-21 11:14:18 +01:00
|
|
|
*/
|
|
|
|
|
2014-09-15 09:13:50 +01:00
|
|
|
/// @memberof is/2
|
2005-09-08 23:06:45 +01:00
|
|
|
static Int
|
2011-03-07 16:02:55 +00:00
|
|
|
p_is( USES_REGS1 )
|
2001-04-09 20:54:03 +01:00
|
|
|
{ /* X is Y */
|
2014-10-22 10:43:38 +01:00
|
|
|
Term out;
|
2014-10-16 10:49:11 +01:00
|
|
|
yap_error_number err;
|
2014-10-15 11:06:07 +01:00
|
|
|
|
2014-10-16 10:49:11 +01:00
|
|
|
Term t = Deref(ARG2);
|
|
|
|
if (IsVarTerm(t)) {
|
|
|
|
Yap_EvalError(INSTANTIATION_ERROR,t, "X is Y");
|
|
|
|
return(FALSE);
|
|
|
|
}
|
2014-10-15 11:06:07 +01:00
|
|
|
Yap_ClearExs();
|
2014-10-16 10:49:11 +01:00
|
|
|
do {
|
|
|
|
out = Yap_InnerEval(Deref(ARG2));
|
|
|
|
if ((err = Yap_FoundArithError()) == YAP_NO_ERROR)
|
|
|
|
break;
|
|
|
|
if (err == RESOURCE_ERROR_STACK) {
|
|
|
|
LOCAL_Error_TYPE = YAP_NO_ERROR;
|
|
|
|
if (!Yap_gcl(LOCAL_Error_Size, 2, ENV, CP)) {
|
|
|
|
Yap_EvalError(RESOURCE_ERROR_STACK, ARG2, LOCAL_ErrorMessage);
|
|
|
|
return FALSE;
|
2010-01-03 17:42:51 +00:00
|
|
|
}
|
2014-10-16 10:49:11 +01:00
|
|
|
} else {
|
|
|
|
Yap_EvalError(err, ARG2, "X is Exp");
|
2014-10-22 10:43:38 +01:00
|
|
|
return FALSE;
|
2014-10-16 10:49:11 +01:00
|
|
|
}
|
|
|
|
} while (TRUE);
|
2009-05-22 17:21:39 +01:00
|
|
|
return Yap_unify_constant(ARG1,out);
|
|
|
|
}
|
2001-04-09 20:54:03 +01:00
|
|
|
|
2014-04-21 11:14:18 +01:00
|
|
|
/**
|
2014-05-14 10:01:11 +01:00
|
|
|
@pred isnan(? X:float) is det
|
2014-04-21 11:14:18 +01:00
|
|
|
|
|
|
|
Interface to the IEE754 `isnan` test.
|
|
|
|
*/
|
|
|
|
|
2014-09-15 09:13:50 +01:00
|
|
|
/// @memberof isnan/1
|
2013-07-16 15:58:57 +01:00
|
|
|
static Int
|
|
|
|
p_isnan( USES_REGS1 )
|
2014-09-15 09:13:50 +01:00
|
|
|
{ /* X isnan Y */
|
2013-07-16 15:58:57 +01:00
|
|
|
Term out = 0L;
|
|
|
|
|
|
|
|
while (!(out = Eval(Deref(ARG1) PASS_REGS))) {
|
|
|
|
if (LOCAL_Error_TYPE == RESOURCE_ERROR_STACK) {
|
|
|
|
LOCAL_Error_TYPE = YAP_NO_ERROR;
|
|
|
|
if (!Yap_gcl(LOCAL_Error_Size, 1, ENV, CP)) {
|
2014-10-16 10:49:11 +01:00
|
|
|
Yap_EvalError(RESOURCE_ERROR_STACK, ARG2, LOCAL_ErrorMessage);
|
2013-07-16 15:58:57 +01:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
} else {
|
2014-10-16 10:49:11 +01:00
|
|
|
Yap_EvalError(LOCAL_Error_TYPE, LOCAL_Error_Term, LOCAL_ErrorMessage);
|
2013-07-16 15:58:57 +01:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (IsVarTerm(out)) {
|
2014-10-16 10:49:11 +01:00
|
|
|
Yap_EvalError(INSTANTIATION_ERROR, out, "isnan/1");
|
2013-07-16 15:58:57 +01:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
if (!IsFloatTerm(out)) {
|
2014-10-16 10:49:11 +01:00
|
|
|
Yap_EvalError(TYPE_ERROR_FLOAT, out, "isnan/1");
|
2013-07-16 15:58:57 +01:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
return isnan(FloatOfTerm(out));
|
|
|
|
}
|
|
|
|
|
2014-04-21 11:14:18 +01:00
|
|
|
/**
|
2014-05-14 10:01:11 +01:00
|
|
|
@pred isinf(? X:float) is det</b>
|
2014-04-21 11:14:18 +01:00
|
|
|
|
|
|
|
Interface to the IEE754 `isinf` test.
|
|
|
|
*/
|
|
|
|
|
2014-09-15 09:13:50 +01:00
|
|
|
/// @memberof isnan/1
|
2013-07-16 15:58:57 +01:00
|
|
|
static Int
|
|
|
|
p_isinf( USES_REGS1 )
|
|
|
|
{ /* X is Y */
|
|
|
|
Term out = 0L;
|
|
|
|
|
|
|
|
while (!(out = Eval(Deref(ARG1) PASS_REGS))) {
|
|
|
|
if (LOCAL_Error_TYPE == RESOURCE_ERROR_STACK) {
|
|
|
|
LOCAL_Error_TYPE = YAP_NO_ERROR;
|
|
|
|
if (!Yap_gcl(LOCAL_Error_Size, 1, ENV, CP)) {
|
2014-10-16 10:49:11 +01:00
|
|
|
Yap_EvalError(RESOURCE_ERROR_STACK, ARG2, LOCAL_ErrorMessage);
|
2013-07-16 15:58:57 +01:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
} else {
|
2014-10-16 10:49:11 +01:00
|
|
|
Yap_EvalError(LOCAL_Error_TYPE, LOCAL_Error_Term, LOCAL_ErrorMessage);
|
2013-07-16 15:58:57 +01:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (IsVarTerm(out)) {
|
2014-10-16 10:49:11 +01:00
|
|
|
Yap_EvalError(INSTANTIATION_ERROR, out, "isinf/1");
|
2013-07-16 15:58:57 +01:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
if (!IsFloatTerm(out)) {
|
2014-10-16 10:49:11 +01:00
|
|
|
Yap_EvalError(TYPE_ERROR_FLOAT, out, "isinf/1");
|
2013-07-16 15:58:57 +01:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
return isinf(FloatOfTerm(out));
|
|
|
|
}
|
|
|
|
|
2014-04-21 11:14:18 +01:00
|
|
|
/**
|
2015-01-04 23:58:23 +00:00
|
|
|
@pred logsum(+ Log1:float, + Log2:float, - Out:float ) is det
|
2014-04-21 11:14:18 +01:00
|
|
|
|
|
|
|
True if _Log1_ is the logarithm of the positive number _A1_,
|
|
|
|
_Log2_ is the logarithm of the positive number _A2_, and
|
|
|
|
_Out_ is the logarithm of the sum of the numbers _A1_ and
|
|
|
|
_A2_. Useful in probability computation.
|
|
|
|
*/
|
2014-09-15 09:13:50 +01:00
|
|
|
|
|
|
|
/// @memberof logsum/3
|
2013-07-25 16:20:33 +01:00
|
|
|
static Int
|
|
|
|
p_logsum( USES_REGS1 )
|
|
|
|
{ /* X is Y */
|
|
|
|
Term t1 = Deref(ARG1);
|
|
|
|
Term t2 = Deref(ARG2);
|
|
|
|
int done = FALSE;
|
|
|
|
Float f1, f2;
|
|
|
|
|
|
|
|
while (!done) {
|
|
|
|
if (IsFloatTerm(t1)) {
|
|
|
|
f1 = FloatOfTerm(t1);
|
|
|
|
done = TRUE;
|
|
|
|
} else if (IsIntegerTerm(t1)) {
|
|
|
|
f1 = IntegerOfTerm(t1);
|
|
|
|
done = TRUE;
|
2013-09-06 23:03:24 +01:00
|
|
|
#if USE_GMP
|
2013-07-25 16:20:33 +01:00
|
|
|
} else if (IsBigIntTerm(t1)) {
|
|
|
|
f1 = Yap_gmp_to_float(t1);
|
|
|
|
done = TRUE;
|
2013-09-06 23:03:24 +01:00
|
|
|
#endif
|
2013-07-25 16:20:33 +01:00
|
|
|
} else {
|
|
|
|
while (!(t1 = Eval(t1 PASS_REGS))) {
|
|
|
|
if (LOCAL_Error_TYPE == RESOURCE_ERROR_STACK) {
|
|
|
|
LOCAL_Error_TYPE = YAP_NO_ERROR;
|
|
|
|
if (!Yap_gcl(LOCAL_Error_Size, 1, ENV, CP)) {
|
2014-10-16 10:49:11 +01:00
|
|
|
Yap_EvalError(RESOURCE_ERROR_STACK, ARG2, LOCAL_ErrorMessage);
|
2013-07-25 16:20:33 +01:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
} else {
|
2014-10-16 10:49:11 +01:00
|
|
|
Yap_EvalError(LOCAL_Error_TYPE, LOCAL_Error_Term, LOCAL_ErrorMessage);
|
2013-07-25 16:20:33 +01:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
done = FALSE;
|
|
|
|
while (!done) {
|
|
|
|
if (IsFloatTerm(t2)) {
|
|
|
|
f2 = FloatOfTerm(t2);
|
|
|
|
done = TRUE;
|
|
|
|
} else if (IsIntegerTerm(t2)) {
|
|
|
|
f2 = IntegerOfTerm(t2);
|
|
|
|
done = TRUE;
|
2013-09-06 23:03:24 +01:00
|
|
|
#if USE_GMP
|
2013-07-25 16:20:33 +01:00
|
|
|
} else if (IsBigIntTerm(t2)) {
|
|
|
|
f2 = Yap_gmp_to_float(t2);
|
|
|
|
done = TRUE;
|
2013-09-06 23:03:24 +01:00
|
|
|
#endif
|
2013-07-25 16:20:33 +01:00
|
|
|
} else {
|
|
|
|
while (!(t2 = Eval(t2 PASS_REGS))) {
|
|
|
|
if (LOCAL_Error_TYPE == RESOURCE_ERROR_STACK) {
|
|
|
|
LOCAL_Error_TYPE = YAP_NO_ERROR;
|
|
|
|
if (!Yap_gcl(LOCAL_Error_Size, 2, ENV, CP)) {
|
2014-10-16 10:49:11 +01:00
|
|
|
Yap_EvalError(RESOURCE_ERROR_STACK, ARG2, LOCAL_ErrorMessage);
|
2013-07-25 16:20:33 +01:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
} else {
|
2014-10-16 10:49:11 +01:00
|
|
|
Yap_EvalError(LOCAL_Error_TYPE, LOCAL_Error_Term, LOCAL_ErrorMessage);
|
2013-07-25 16:20:33 +01:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (f1 >= f2) {
|
|
|
|
Float fi = exp(f2-f1);
|
|
|
|
return Yap_unify(ARG3,MkFloatTerm(f1+log(1+fi)));
|
|
|
|
} else {
|
|
|
|
Float fi = exp(f1-f2);
|
|
|
|
return Yap_unify(ARG3,MkFloatTerm(f2+log(1+fi)));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-09-15 09:13:50 +01:00
|
|
|
|
2009-05-22 17:21:39 +01:00
|
|
|
Int
|
|
|
|
Yap_ArithError(yap_error_number type, Term where, char *format,...)
|
|
|
|
{
|
2011-03-07 16:02:55 +00:00
|
|
|
CACHE_REGS
|
2009-05-22 17:21:39 +01:00
|
|
|
va_list ap;
|
|
|
|
|
2014-10-16 10:49:11 +01:00
|
|
|
if (LOCAL_ArithError)
|
|
|
|
return 0L;
|
2011-05-04 10:11:41 +01:00
|
|
|
LOCAL_ArithError = TRUE;
|
2011-05-23 16:19:47 +01:00
|
|
|
LOCAL_Error_TYPE = type;
|
|
|
|
LOCAL_Error_Term = where;
|
|
|
|
if (!LOCAL_ErrorMessage)
|
|
|
|
LOCAL_ErrorMessage = LOCAL_ErrorSay;
|
2009-05-22 17:21:39 +01:00
|
|
|
va_start (ap, format);
|
|
|
|
if (format != NULL) {
|
|
|
|
#if HAVE_VSNPRINTF
|
2011-05-23 16:19:47 +01:00
|
|
|
(void) vsnprintf(LOCAL_ErrorMessage, MAX_ERROR_MSG_SIZE, format, ap);
|
2009-05-22 17:21:39 +01:00
|
|
|
#else
|
2011-05-23 16:19:47 +01:00
|
|
|
(void) vsprintf(LOCAL_ErrorMessage, format, ap);
|
2009-05-22 17:21:39 +01:00
|
|
|
#endif
|
|
|
|
} else {
|
2011-05-23 16:19:47 +01:00
|
|
|
LOCAL_ErrorMessage[0] = '\0';
|
2006-01-02 02:16:19 +00:00
|
|
|
}
|
2009-05-22 17:21:39 +01:00
|
|
|
va_end (ap);
|
|
|
|
return 0L;
|
2001-04-09 20:54:03 +01:00
|
|
|
}
|
|
|
|
|
2014-10-16 10:49:11 +01:00
|
|
|
yamop *
|
|
|
|
Yap_EvalError(yap_error_number type, Term where, char *format,...)
|
|
|
|
{
|
|
|
|
CACHE_REGS
|
|
|
|
va_list ap;
|
|
|
|
|
|
|
|
if (LOCAL_ArithError) {
|
2014-10-20 00:33:36 +01:00
|
|
|
LOCAL_ArithError = YAP_NO_ERROR;
|
2014-10-16 10:49:11 +01:00
|
|
|
return Yap_Error( LOCAL_Error_TYPE, LOCAL_Error_Term, LOCAL_ErrorMessage);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!LOCAL_ErrorMessage)
|
|
|
|
LOCAL_ErrorMessage = LOCAL_ErrorSay;
|
|
|
|
va_start (ap, format);
|
|
|
|
if (format != NULL) {
|
|
|
|
#if HAVE_VSNPRINTF
|
|
|
|
(void) vsnprintf(LOCAL_ErrorMessage, MAX_ERROR_MSG_SIZE, format, ap);
|
|
|
|
#else
|
|
|
|
(void) vsprintf(LOCAL_ErrorMessage, format, ap);
|
|
|
|
#endif
|
|
|
|
} else {
|
|
|
|
LOCAL_ErrorMessage[0] = '\0';
|
|
|
|
}
|
|
|
|
va_end (ap);
|
|
|
|
return Yap_Error( type, where, LOCAL_ErrorMessage);
|
|
|
|
}
|
|
|
|
|
2014-05-14 10:01:11 +01:00
|
|
|
/**
|
|
|
|
|
2015-01-04 23:58:23 +00:00
|
|
|
@pred between(+ Low:int, + High:int, ? Value:int) is nondet
|
2014-05-14 10:01:11 +01:00
|
|
|
|
|
|
|
_Low_ and _High_ are integers, _High_ \>= _Low_. If
|
|
|
|
_Value_ is an integer, _Low_ =\< _Value_
|
|
|
|
=\< _High_. When _Value_ is a variable it is successively
|
|
|
|
bound to all integers between _Low_ and _High_. If
|
|
|
|
_High_ is inf or infinite between/3 is true iff
|
|
|
|
_Value_ \>= _Low_, a feature that is particularly interesting
|
|
|
|
for generating integers from a certain value.
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
2014-09-15 09:13:50 +01:00
|
|
|
/// @memberof between/3
|
2013-04-30 00:22:53 +01:00
|
|
|
static Int cont_between( USES_REGS1 )
|
|
|
|
{
|
|
|
|
Term t1 = EXTRA_CBACK_ARG(3,1);
|
|
|
|
Term t2 = EXTRA_CBACK_ARG(3,2);
|
|
|
|
|
|
|
|
Yap_unify(ARG3, t1);
|
2013-04-30 21:23:01 +01:00
|
|
|
if (IsIntegerTerm(t1)) {
|
2013-04-30 00:22:53 +01:00
|
|
|
Int i1;
|
|
|
|
Term tn;
|
|
|
|
|
|
|
|
if (t1 == t2)
|
|
|
|
cut_succeed();
|
|
|
|
i1 = IntegerOfTerm(t1);
|
2013-04-30 21:23:01 +01:00
|
|
|
tn = add_int(i1, 1 PASS_REGS);
|
|
|
|
EXTRA_CBACK_ARG(3,1) = tn;
|
2014-01-19 21:15:05 +00:00
|
|
|
HB = B->cp_h = HR;
|
2013-04-30 00:22:53 +01:00
|
|
|
return TRUE;
|
|
|
|
} else {
|
|
|
|
Term t[2];
|
|
|
|
Term tn;
|
|
|
|
Int cmp;
|
|
|
|
|
2013-05-02 01:27:09 +01:00
|
|
|
cmp = Yap_acmp(t1, t2 PASS_REGS);
|
2013-04-30 00:22:53 +01:00
|
|
|
if (cmp == 0)
|
|
|
|
cut_succeed();
|
|
|
|
t[0] = t1;
|
|
|
|
t[1] = MkIntTerm(1);
|
2013-05-02 01:27:09 +01:00
|
|
|
tn = Eval(Yap_MkApplTerm(FunctorPlus, 2, t) PASS_REGS);
|
2013-04-30 00:22:53 +01:00
|
|
|
EXTRA_CBACK_ARG(3,1) = tn;
|
2014-01-19 21:15:05 +00:00
|
|
|
HB = B->cp_h = HR;
|
2013-04-30 00:22:53 +01:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-09-15 09:13:50 +01:00
|
|
|
/// @memberof between/3
|
2013-04-30 00:22:53 +01:00
|
|
|
static Int
|
|
|
|
init_between( USES_REGS1 )
|
|
|
|
{
|
|
|
|
Term t1 = Deref(ARG1);
|
|
|
|
Term t2 = Deref(ARG2);
|
|
|
|
|
|
|
|
if (IsVarTerm(t1)) {
|
2014-10-16 10:49:11 +01:00
|
|
|
Yap_EvalError(INSTANTIATION_ERROR, t1, "between/3");
|
2013-04-30 00:22:53 +01:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
if (IsVarTerm(t2)) {
|
2014-10-16 10:49:11 +01:00
|
|
|
Yap_EvalError(INSTANTIATION_ERROR, t1, "between/3");
|
2013-04-30 00:22:53 +01:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
if (!IsIntegerTerm(t1) &&
|
|
|
|
!IsBigIntTerm(t1)) {
|
2014-10-16 10:49:11 +01:00
|
|
|
Yap_EvalError(TYPE_ERROR_INTEGER, t1, "between/3");
|
2013-04-30 00:22:53 +01:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
if (!IsIntegerTerm(t2) &&
|
|
|
|
!IsBigIntTerm(t2) &&
|
|
|
|
t2 != MkAtomTerm(AtomInf) &&
|
|
|
|
t2 != MkAtomTerm(AtomInfinity)) {
|
2014-10-16 10:49:11 +01:00
|
|
|
Yap_EvalError(TYPE_ERROR_INTEGER, t2, "between/3");
|
2013-04-30 00:22:53 +01:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
if (IsIntegerTerm(t1) && IsIntegerTerm(t2)) {
|
|
|
|
Int i1 = IntegerOfTerm(t1);
|
|
|
|
Int i2 = IntegerOfTerm(t2);
|
|
|
|
Term t3;
|
|
|
|
|
|
|
|
t3 = Deref(ARG3);
|
|
|
|
if (!IsVarTerm(t3)) {
|
|
|
|
if (!IsIntegerTerm(t3)) {
|
|
|
|
if (!IsBigIntTerm(t3)) {
|
2014-10-16 10:49:11 +01:00
|
|
|
Yap_EvalError(TYPE_ERROR_INTEGER, t3, "between/3");
|
2013-04-30 00:22:53 +01:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
cut_fail();
|
|
|
|
} else {
|
|
|
|
Int i3 = IntegerOfTerm(t3);
|
|
|
|
if (i3 >= i1 && i3 <= i2)
|
|
|
|
cut_succeed();
|
|
|
|
cut_fail();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (i1 > i2) cut_fail();
|
|
|
|
if (i1 == i2) {
|
|
|
|
Yap_unify(ARG3, t1);
|
|
|
|
cut_succeed();
|
|
|
|
}
|
|
|
|
} else if (IsIntegerTerm(t1) && IsAtomTerm(t2)) {
|
|
|
|
Int i1 = IntegerOfTerm(t1);
|
|
|
|
Term t3;
|
|
|
|
|
|
|
|
t3 = Deref(ARG3);
|
|
|
|
if (!IsVarTerm(t3)) {
|
|
|
|
if (!IsIntegerTerm(t3)) {
|
|
|
|
if (!IsBigIntTerm(t3)) {
|
2014-10-16 10:49:11 +01:00
|
|
|
Yap_EvalError(TYPE_ERROR_INTEGER, t3, "between/3");
|
2013-04-30 00:22:53 +01:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
cut_fail();
|
|
|
|
} else {
|
|
|
|
Int i3 = IntegerOfTerm(t3);
|
|
|
|
if (i3 >= i1)
|
|
|
|
cut_succeed();
|
|
|
|
cut_fail();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
Term t3 = Deref(ARG3);
|
|
|
|
Int cmp;
|
|
|
|
|
|
|
|
if (!IsVarTerm(t3)) {
|
|
|
|
if (!IsIntegerTerm(t3) && !IsBigIntTerm(t3)) {
|
2014-10-16 10:49:11 +01:00
|
|
|
Yap_EvalError(TYPE_ERROR_INTEGER, t3, "between/3");
|
2013-04-30 00:22:53 +01:00
|
|
|
return FALSE;
|
|
|
|
}
|
2013-05-02 01:27:09 +01:00
|
|
|
if (Yap_acmp(t3, t1 PASS_REGS) >= 0 && Yap_acmp(t2,t3 PASS_REGS) >= 0 && P != FAILCODE)
|
2013-04-30 00:22:53 +01:00
|
|
|
cut_succeed();
|
|
|
|
cut_fail();
|
|
|
|
}
|
2013-05-02 01:27:09 +01:00
|
|
|
cmp = Yap_acmp(t1, t2 PASS_REGS);
|
2013-04-30 00:22:53 +01:00
|
|
|
if (cmp > 0) cut_fail();
|
|
|
|
if (cmp == 0) {
|
|
|
|
Yap_unify(ARG3, t1);
|
|
|
|
cut_succeed();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
EXTRA_CBACK_ARG(3,1) = t1;
|
|
|
|
EXTRA_CBACK_ARG(3,2) = t2;
|
|
|
|
return cont_between( PASS_REGS1 );
|
|
|
|
}
|
|
|
|
|
2001-04-09 20:54:03 +01:00
|
|
|
void
|
2002-11-18 18:18:05 +00:00
|
|
|
Yap_InitEval(void)
|
2001-04-09 20:54:03 +01:00
|
|
|
{
|
|
|
|
/* here are the arithmetical predicates */
|
2002-11-18 18:18:05 +00:00
|
|
|
Yap_InitConstExps();
|
|
|
|
Yap_InitUnaryExps();
|
|
|
|
Yap_InitBinaryExps();
|
2010-01-03 17:42:51 +00:00
|
|
|
Yap_InitCPred("is", 2, p_is, 0L);
|
2013-07-16 15:58:57 +01:00
|
|
|
Yap_InitCPred("isnan", 1, p_isnan, TestPredFlag);
|
|
|
|
Yap_InitCPred("isinf", 1, p_isinf, TestPredFlag);
|
2013-07-25 16:20:33 +01:00
|
|
|
Yap_InitCPred("logsum", 3, p_logsum, TestPredFlag);
|
2013-04-30 00:22:53 +01:00
|
|
|
Yap_InitCPredBack("between", 3, 2, init_between, cont_between, 0);
|
2001-04-09 20:54:03 +01:00
|
|
|
}
|
|
|
|
|
2014-07-17 18:19:38 +01:00
|
|
|
/**
|
|
|
|
*
|
|
|
|
* @}
|
|
|
|
*/
|