ISO/IEC JTC1 SC22 WG17 Post-N224
Evaluable functors, current practice

Ulrich Neumerkel (Version history)
This is the final state of the document as it was used for the resolutions in Edinburgh. In the meantime many systems adopted accordingly. This document is superseded by DTC2.
In 13211-1:1995 evaluable functors (9) are used for evaluating an expression (7.9) within Arithmetic evaluation (8.6) and Arithmetic comparison (8.7). This document provides an overview of the current practice of evaluable functors that are not part of 13211-1 but are compliant (5.1) due to:
5.5.10 Evaluable functors
A processor may support one or more additional evaluable
functors (9) as an implementation specific feature.

Summary of evaluable functors in 13211-1:1995

9.1 The simple arithmetic functors: (+)/2, (-)/2, (*)/2, (//)/2, (/)/2, (rem)/2, (mod)/2, (-)/1, abs/1, sign/1, float_integer_part/1, float_fractional_part/1, float/1, floor/1, truncate/1, round/1, ceiling/1.
9.3 Other arithmetic functors: (**)/2, sin/1, cos/1, atan/1, exp/1, log/1, sqrt/1.
9.4 Bitwise functors: (>>)/2, (<<)/2, (/\)/2, (\/)/2, (\)/1.

Implementation specific evaluable functors

Implementors interested in standardization who wish to see their system listed in this table are asked to provide a table in HTML with the complete first row and one row for their system. If the same function is provided with an alternate name, the entry shall be labelled "alt". Functions added since the Pasadena meeting shall be labelled "new".

core core pllib cuf B IF SICStus YAP SWI ECLiPSe GNU
Functor 2008-11-17 2009-07-17 7B 7.3V5.33.12
(+)/1 9.1 9.1 yes yesyesyesyesyesyesyes
max/2 yesyesyesyesyesyesyes
min/2 yesyesyesyesyesyesyes
acos/1 9.5.5 9.5.5 yes yesyesyesyesyesyesyes
asin/1 9.5.4 9.5.4 yes yesyesyesyesyesyesyes
tan/1 9.5.3 9.5.3 yes yesyesyesyesyesyesnew
pi/0 9.7.1 9.7.1 yes yesyes yesyesyesnew
xor/2 yes newaltaltaltyesyesalt
(#)/2 alt yesyesyesaltaltalt
(><)/2 9.4.6 9.4.6 alt altaltaltnewaltnew
atan2/2 yes new yesyesaltaltalt
atan/2 9.5.6 9.5.6 alt altaltnewyesnew
(^)/2 new any yes yesyesyesnew
(div)/2 yes newyes newnewyesnew
e/0 9.7.2 9.7.2 yes yes yesyesyesnew
log10/1 yesyes new
msb/1 yesyesyes new
lsb/1 newyes new
popcount/1 newyes new
clrbit/2 yes
getbit/2 yes
setbit/2 yes
log1p/1 ?
expm1/1 ?
signum/1 yes alt
sgn/1 yes
gcd/2 9.3.9 9.3.9 yes yesyesyesyesnew
lcm/2 yes
eval/1 yesyes
nexttoward/2 yes
copysign/2 yesyes
extensibility - - ? yesyes
Further SICStus 3: acot/1 acot2/2 acoth/1 cot/1 coth/1


1 (#)/2 vs. (><)/2 vs. xor/2. (#)/2 is conflicting or irritating w.r.t constraints. (><)/2 suggests to be something similar to a relational operator like (>)/2. xor/2 says what it is, but isn't an operator. Adding xor as operator seems problematic. This voids Prolog text like (a, b, xor).

2 Original name: atan2/2 vs. replacement atan/2. In favor of atan2/2: All other languages/libraries call it atan2. Cannot be confused with atan/1 of 13211-1:1995.

3 (^)/2 - missing for unbounded integers. (**)/2 has as result type float only. This is useful for arguments of type float or bounded integers. But for unbounded integers the result type should be an unbounded integer. To avoid compatibility problems a new name seems to be the best. Also, (**)/2 is declared as op(200,xfx,**). in the operator table This means that 7**7**7. is invalid Prolog text, whereas 7^7^7. is valid with the correct associativity. ^ is used also in Haskell. An addition seems to be less problematic than a change.

4 Instead of e one can write exp(1).

5 div/2 is defined as:

div(X, Y, Z) :-
    Z is (X - X mod Y) // Y.

ECLiPSe remarks

signum/1 and sgn/1 always return an integer (-1, 0 or 1).

In ECLiPSe native mode, floor, ceiling, round and truncate always return a result of the same type as the argument.

integer/1 is a pure type conversion (like float/1). It converts its argument to integer type iff it has an integral value. Otherwise it raises an exception. The purpose is to convert the results of sign/1 or float_integer_part/1 (and non-standard versions of round, truncate, floor, ceiling) to integers, if needed.

setbit(X,Y) sets bit Y in X. Bits are counted from 0 (lsb).

div/2 is the division that goes with mod/2, while (//)/2 goes with rem/2.

eval/1 is used to mark variables that may be instantiated to a symbolic expression (rather than a number) at runtime. See this thread in comp.lang.prolog.

In ECLiPSe, any deterministic predicate that returns a number as its last argument can be used as an arithmetic function, e.g. atom_length(hello) will evaluate to 5 via calling atom_length/2. Arguments of such expressions are not recursively evaluated (unless this is done explicitly by the corresponding predicate), and therefore do not need to be arithmetic expressions themselves.

Criteria for inclusion

Arithmetic comparison

8.7.1 (=:=)/2, (=\=)/2, (<)/2, (=<)/2, (>)/2, (>=)/2.

8.7.2 (>=<)/2 arithmetic comparable

>=<(E1, E2) is true iff the corresponding evaluated values EV1 and EV2 are comparable numbers.
E1 >=< E2 evaluates E1 to V1 and E2 to V2; this process may raise exceptions, including if V1 or V2 is not something the processor recognises as a number.

It succeeds if V1 and V2 are comparable numbers. It fails if V1 and V2 are numbers that are not comparable.

It needs some standardese around to it allow for the possibility that V1, V2, or both might be constrained and the constraints might be such as to determine the order.

This is intended to be the IEEE "?" comparison, but needs to be described so that a Prolog that allows complex numbers (as C99 does, which could be used to implement it) could use it to avoid trying to order complex numbers.

At least one Prolog with rational arithmetic had rational ±infinity and rational NaN, so it would have had a use for this too.

Validated HTML