diff --git a/C/eval.c b/C/eval.c index 21634f13f..142f4dce4 100644 --- a/C/eval.c +++ b/C/eval.c @@ -254,6 +254,74 @@ p_isinf( USES_REGS1 ) return isinf(FloatOfTerm(out)); } +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; + } else if (IsBigIntTerm(t1)) { + f1 = Yap_gmp_to_float(t1); + done = TRUE; + } 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; + } else if (IsBigIntTerm(t2)) { + f2 = Yap_gmp_to_float(t2); + done = TRUE; + } 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))); + } +} + Int Yap_ArithError(yap_error_number type, Term where, char *format,...) { @@ -418,6 +486,7 @@ Yap_InitEval(void) Yap_InitCPred("is", 2, p_is, 0L); Yap_InitCPred("isnan", 1, p_isnan, TestPredFlag); Yap_InitCPred("isinf", 1, p_isinf, TestPredFlag); + Yap_InitCPred("logsum", 3, p_logsum, TestPredFlag); Yap_InitCPredBack("between", 3, 2, init_between, cont_between, 0); } diff --git a/docs/yap.tex b/docs/yap.tex index 743b4270d..d9d4f73f4 100644 --- a/docs/yap.tex +++ b/docs/yap.tex @@ -4459,6 +4459,15 @@ The following predicates provide counting: True if @var{Int3} = @var{Int1} + @var{Int2}. At least two of the three arguments must be instantiated to integers. +@item logsum(+@var{Log1}, +@var{Log2}, -@var{Out} ) +@findex logsum/3 +@snindex logsum/3 +@cnindex logsum/3 + True if @var{Log1} is the logarithm of the positive number @var{A1}, + @var{Log2} is the logarithm of the positive number @var{A2}, and + @var{Out} is the logarithm of the sum of the numbers @var{A1} and + @var{A2}. Useful in probability computation. + @item isnan(+@var{Float}) @findex isnan/1 @snindex isnan/1