| 
									
										
										
										
											2001-04-09 19:54:03 +00: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
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-04-21 11:14:18 +01:00
										 |  |  | /**
 | 
					
						
							|  |  |  |    @file eval.c | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    @defgroup arithmetic_preds Arithmetic Predicates | 
					
						
							|  |  |  |    @ingroup arithmetic | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    @{ | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-04-09 19:54:03 +00:00
										 |  |  | #include "Yap.h"
 | 
					
						
							|  |  |  | #include "Yatom.h"
 | 
					
						
							| 
									
										
										
										
											2009-10-23 14:22:17 +01:00
										 |  |  | #include "YapHeap.h"
 | 
					
						
							| 
									
										
										
										
											2001-04-09 19:54:03 +00:00
										 |  |  | #include "eval.h"
 | 
					
						
							| 
									
										
										
										
											2009-05-22 14:44:32 -05:00
										 |  |  | #if HAVE_STDARG_H
 | 
					
						
							|  |  |  | #include <stdarg.h>
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | #include <stdlib.h>
 | 
					
						
							|  |  |  | #if HAVE_UNISTD_H
 | 
					
						
							|  |  |  | #include <unistd.h>
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2001-04-09 19:54:03 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-27 12:36:48 +02:00
										 |  |  | static Term Eval(Term t1 USES_REGS); | 
					
						
							| 
									
										
										
										
											2011-05-25 16:40:36 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-27 12:36:48 +02: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 19:54:03 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | static Term | 
					
						
							| 
									
										
										
										
											2011-03-07 16:02:55 +00:00
										 |  |  | Eval(Term t USES_REGS) | 
					
						
							| 
									
										
										
										
											2001-04-09 19:54:03 +00:00
										 |  |  | { | 
					
						
							|  |  |  |   if (IsVarTerm(t)) { | 
					
						
							| 
									
										
										
										
											2011-05-04 10:11:41 +01:00
										 |  |  |     LOCAL_ArithError = TRUE; | 
					
						
							| 
									
										
										
										
											2009-05-22 11:21:39 -05: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 12:28:02 +00:00
										 |  |  |       /* error */ | 
					
						
							| 
									
										
										
										
											2010-02-26 12:01:08 +00:00
										 |  |  |       return Yap_ArithError(TYPE_ERROR_EVALUABLE, t, | 
					
						
							| 
									
										
										
										
											2009-05-22 11:24:44 -05:00
										 |  |  | 			    "atom %s for arithmetic expression", | 
					
						
							|  |  |  | 			    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 19:54:03 +00: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 11:21:39 -05: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 12:36:48 +02: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 19:54:03 +00: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 19:54:03 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2008-12-04 23:33:32 +00:00
										 |  |  |   } /* else if (IsPairTerm(t)) */ { | 
					
						
							| 
									
										
										
										
											2008-04-08 15:36:53 +00:00
										 |  |  |     if (TailOfTerm(t) != TermNil) { | 
					
						
							| 
									
										
										
										
											2009-05-22 11:24:44 -05:00
										 |  |  |       return Yap_ArithError(TYPE_ERROR_EVALUABLE, t, | 
					
						
							|  |  |  | 			    "string must contain a single character to be evaluated as an arithmetic expression"); | 
					
						
							| 
									
										
										
										
											2001-04-09 19:54:03 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2011-03-07 16:02:55 +00:00
										 |  |  |     return Eval(HeadOfTerm(t) PASS_REGS); | 
					
						
							| 
									
										
										
										
											2001-04-09 19:54:03 +00:00
										 |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-04 23:33:32 +00:00
										 |  |  | Term | 
					
						
							| 
									
										
										
										
											2010-01-04 21:16:42 -02:00
										 |  |  | Yap_InnerEval(Term t) | 
					
						
							| 
									
										
										
										
											2008-12-04 23:33:32 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2011-03-07 16:02:55 +00:00
										 |  |  |   CACHE_REGS | 
					
						
							|  |  |  |   return Eval(t PASS_REGS); | 
					
						
							| 
									
										
										
										
											2008-12-04 23:33:32 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-09-08 22:06:45 +00: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`. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-09-08 22:06:45 +00:00
										 |  |  | static Int | 
					
						
							| 
									
										
										
										
											2011-03-07 16:02:55 +00:00
										 |  |  | p_is( USES_REGS1 ) | 
					
						
							| 
									
										
										
										
											2001-04-09 19:54:03 +00:00
										 |  |  | {				/* X is Y	 */ | 
					
						
							| 
									
										
										
										
											2010-01-03 15:42:51 -02:00
										 |  |  |   Term out = 0L; | 
					
						
							| 
									
										
										
										
											2009-05-22 11:21:39 -05:00
										 |  |  |    | 
					
						
							| 
									
										
										
										
											2011-03-07 16:02:55 +00:00
										 |  |  |   while (!(out = Eval(Deref(ARG2) PASS_REGS))) { | 
					
						
							| 
									
										
										
										
											2011-05-23 16:19:47 +01:00
										 |  |  |     if (LOCAL_Error_TYPE == RESOURCE_ERROR_STACK) { | 
					
						
							|  |  |  |       LOCAL_Error_TYPE = YAP_NO_ERROR; | 
					
						
							|  |  |  |       if (!Yap_gcl(LOCAL_Error_Size, 2, ENV, CP)) { | 
					
						
							|  |  |  | 	Yap_Error(RESOURCE_ERROR_STACK, ARG2, LOCAL_ErrorMessage); | 
					
						
							| 
									
										
										
										
											2010-01-03 15:42:51 -02:00
										 |  |  | 	return FALSE; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } else { | 
					
						
							| 
									
										
										
										
											2011-05-23 16:19:47 +01:00
										 |  |  |       Yap_Error(LOCAL_Error_TYPE, LOCAL_Error_Term, LOCAL_ErrorMessage); | 
					
						
							| 
									
										
										
										
											2010-01-03 15:42:51 -02:00
										 |  |  |       return FALSE; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2009-05-22 11:21:39 -05:00
										 |  |  |   return Yap_unify_constant(ARG1,out); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2001-04-09 19:54:03 +00: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. | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-07-16 09:58:57 -05:00
										 |  |  | static Int | 
					
						
							|  |  |  | p_isnan( 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)) { | 
					
						
							|  |  |  | 	Yap_Error(RESOURCE_ERROR_STACK, ARG2, LOCAL_ErrorMessage); | 
					
						
							|  |  |  | 	return FALSE; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |       Yap_Error(LOCAL_Error_TYPE, LOCAL_Error_Term, LOCAL_ErrorMessage); | 
					
						
							|  |  |  |       return FALSE; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   if (IsVarTerm(out)) { | 
					
						
							|  |  |  |     Yap_Error(INSTANTIATION_ERROR, out, "isnan/1"); | 
					
						
							|  |  |  |     return FALSE; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   if (!IsFloatTerm(out)) { | 
					
						
							|  |  |  |     Yap_Error(TYPE_ERROR_FLOAT, out, "isnan/1"); | 
					
						
							|  |  |  |     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. | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-07-16 09:58:57 -05: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)) { | 
					
						
							|  |  |  |         Yap_Error(RESOURCE_ERROR_STACK, ARG2, LOCAL_ErrorMessage); | 
					
						
							|  |  |  |         return FALSE; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |       Yap_Error(LOCAL_Error_TYPE, LOCAL_Error_Term, LOCAL_ErrorMessage); | 
					
						
							|  |  |  |       return FALSE; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   if (IsVarTerm(out)) { | 
					
						
							|  |  |  |     Yap_Error(INSTANTIATION_ERROR, out, "isinf/1"); | 
					
						
							|  |  |  |     return FALSE; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   if (!IsFloatTerm(out)) { | 
					
						
							|  |  |  |     Yap_Error(TYPE_ERROR_FLOAT, out, "isinf/1"); | 
					
						
							|  |  |  |     return FALSE; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   return isinf(FloatOfTerm(out)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-04-21 11:14:18 +01:00
										 |  |  | /**
 | 
					
						
							| 
									
										
										
										
											2014-05-14 10:01:11 +01: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. | 
					
						
							|  |  |  | */ | 
					
						
							| 
									
										
										
										
											2013-07-25 10:20:33 -05: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 10:20:33 -05: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 10:20:33 -05: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)) { | 
					
						
							|  |  |  | 	    Yap_Error(RESOURCE_ERROR_STACK, ARG2, LOCAL_ErrorMessage); | 
					
						
							|  |  |  | 	    return FALSE; | 
					
						
							|  |  |  | 	  } | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 	  Yap_Error(LOCAL_Error_TYPE, LOCAL_Error_Term, LOCAL_ErrorMessage); | 
					
						
							|  |  |  | 	  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 10:20:33 -05: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 10:20:33 -05: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)) { | 
					
						
							|  |  |  | 	    Yap_Error(RESOURCE_ERROR_STACK, ARG2, LOCAL_ErrorMessage); | 
					
						
							|  |  |  | 	    return FALSE; | 
					
						
							|  |  |  | 	  } | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 	  Yap_Error(LOCAL_Error_TYPE, LOCAL_Error_Term, LOCAL_ErrorMessage); | 
					
						
							|  |  |  | 	  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))); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-22 11:21:39 -05: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 11:21:39 -05:00
										 |  |  |   va_list ap; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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 11:21:39 -05: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 11:21:39 -05:00
										 |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2011-05-23 16:19:47 +01:00
										 |  |  |     (void) vsprintf(LOCAL_ErrorMessage, format, ap); | 
					
						
							| 
									
										
										
										
											2009-05-22 11:21:39 -05: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 11:21:39 -05:00
										 |  |  |   va_end (ap); | 
					
						
							|  |  |  |   return 0L; | 
					
						
							| 
									
										
										
										
											2001-04-09 19:54:03 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-14 10:01:11 +01:00
										 |  |  | /**
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    @{ | 
					
						
							|  |  |  |   | 
					
						
							|  |  |  |   @pred between(+ Low:int, + High:int, ? Value:int) is nondet | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    _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. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-04-29 18:22:53 -05: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 15:23:01 -05:00
										 |  |  |   if (IsIntegerTerm(t1)) { | 
					
						
							| 
									
										
										
										
											2013-04-29 18:22:53 -05:00
										 |  |  |     Int i1; | 
					
						
							|  |  |  |     Term tn; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (t1 == t2) | 
					
						
							|  |  |  |       cut_succeed(); | 
					
						
							|  |  |  |     i1 = IntegerOfTerm(t1); | 
					
						
							| 
									
										
										
										
											2013-04-30 15:23:01 -05: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-29 18:22:53 -05:00
										 |  |  |     return TRUE; | 
					
						
							|  |  |  |   } else { | 
					
						
							|  |  |  |     Term t[2]; | 
					
						
							|  |  |  |     Term tn; | 
					
						
							|  |  |  |     Int cmp; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-01 19:27:09 -05:00
										 |  |  |     cmp = Yap_acmp(t1, t2 PASS_REGS); | 
					
						
							| 
									
										
										
										
											2013-04-29 18:22:53 -05:00
										 |  |  |     if (cmp == 0) | 
					
						
							|  |  |  |       cut_succeed(); | 
					
						
							|  |  |  |     t[0] = t1; | 
					
						
							|  |  |  |     t[1] = MkIntTerm(1); | 
					
						
							| 
									
										
										
										
											2013-05-01 19:27:09 -05:00
										 |  |  |     tn = Eval(Yap_MkApplTerm(FunctorPlus, 2, t) PASS_REGS); | 
					
						
							| 
									
										
										
										
											2013-04-29 18:22:53 -05:00
										 |  |  |     EXTRA_CBACK_ARG(3,1) = tn; | 
					
						
							| 
									
										
										
										
											2014-01-19 21:15:05 +00:00
										 |  |  |     HB = B->cp_h = HR; | 
					
						
							| 
									
										
										
										
											2013-04-29 18:22:53 -05:00
										 |  |  |     return TRUE; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static Int | 
					
						
							|  |  |  | init_between( USES_REGS1 ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   Term t1 = Deref(ARG1); | 
					
						
							|  |  |  |   Term t2 = Deref(ARG2); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (IsVarTerm(t1)) { | 
					
						
							|  |  |  |     Yap_Error(INSTANTIATION_ERROR, t1, "between/3"); | 
					
						
							|  |  |  |     return FALSE; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   if (IsVarTerm(t2)) { | 
					
						
							|  |  |  |     Yap_Error(INSTANTIATION_ERROR, t1, "between/3"); | 
					
						
							|  |  |  |     return FALSE; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   if (!IsIntegerTerm(t1) &&  | 
					
						
							|  |  |  |       !IsBigIntTerm(t1)) { | 
					
						
							|  |  |  |     Yap_Error(TYPE_ERROR_INTEGER, t1, "between/3"); | 
					
						
							|  |  |  |     return FALSE; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   if (!IsIntegerTerm(t2) &&  | 
					
						
							|  |  |  |       !IsBigIntTerm(t2) && | 
					
						
							|  |  |  |       t2 != MkAtomTerm(AtomInf) && | 
					
						
							|  |  |  |       t2 != MkAtomTerm(AtomInfinity)) { | 
					
						
							|  |  |  |     Yap_Error(TYPE_ERROR_INTEGER, t2, "between/3"); | 
					
						
							|  |  |  |     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)) { | 
					
						
							|  |  |  | 	  Yap_Error(TYPE_ERROR_INTEGER, t3, "between/3"); | 
					
						
							|  |  |  | 	  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)) { | 
					
						
							|  |  |  | 	  Yap_Error(TYPE_ERROR_INTEGER, t3, "between/3"); | 
					
						
							|  |  |  | 	  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)) { | 
					
						
							|  |  |  | 	Yap_Error(TYPE_ERROR_INTEGER, t3, "between/3"); | 
					
						
							|  |  |  | 	return FALSE; | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2013-05-01 19:27:09 -05:00
										 |  |  |       if (Yap_acmp(t3, t1 PASS_REGS) >= 0 && Yap_acmp(t2,t3 PASS_REGS) >= 0 && P != FAILCODE) | 
					
						
							| 
									
										
										
										
											2013-04-29 18:22:53 -05:00
										 |  |  | 	cut_succeed(); | 
					
						
							|  |  |  |       cut_fail(); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2013-05-01 19:27:09 -05:00
										 |  |  |     cmp = Yap_acmp(t1, t2 PASS_REGS); | 
					
						
							| 
									
										
										
										
											2013-04-29 18:22:53 -05: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 ); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-14 10:01:11 +01:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * @} | 
					
						
							|  |  |  |  *  | 
					
						
							|  |  |  |  * @} | 
					
						
							|  |  |  | */ | 
					
						
							| 
									
										
										
										
											2001-04-09 19:54:03 +00:00
										 |  |  | void | 
					
						
							| 
									
										
										
										
											2002-11-18 18:18:05 +00:00
										 |  |  | Yap_InitEval(void) | 
					
						
							| 
									
										
										
										
											2001-04-09 19:54:03 +00:00
										 |  |  | { | 
					
						
							|  |  |  |   /* here are the arithmetical predicates */ | 
					
						
							| 
									
										
										
										
											2002-11-18 18:18:05 +00:00
										 |  |  |   Yap_InitConstExps(); | 
					
						
							|  |  |  |   Yap_InitUnaryExps(); | 
					
						
							|  |  |  |   Yap_InitBinaryExps(); | 
					
						
							| 
									
										
										
										
											2010-01-03 15:42:51 -02:00
										 |  |  |   Yap_InitCPred("is", 2, p_is, 0L); | 
					
						
							| 
									
										
										
										
											2013-07-16 09:58:57 -05:00
										 |  |  |   Yap_InitCPred("isnan", 1, p_isnan, TestPredFlag); | 
					
						
							|  |  |  |   Yap_InitCPred("isinf", 1, p_isinf, TestPredFlag); | 
					
						
							| 
									
										
										
										
											2013-07-25 10:20:33 -05:00
										 |  |  |   Yap_InitCPred("logsum", 3, p_logsum, TestPredFlag); | 
					
						
							| 
									
										
										
										
											2013-04-29 18:22:53 -05:00
										 |  |  |   Yap_InitCPredBack("between", 3, 2, init_between, cont_between, 0); | 
					
						
							| 
									
										
										
										
											2001-04-09 19:54:03 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 |