Arithmetic Functions

## 8.3 Arithmetic Functions

- Predefined Arithmetic Functions
- Evaluation Mechanism
- User Defined Arithmetic Functions
- Runtime Expressions

### 8.3.1 Predefined Arithmetic Functions

The following predefined arithmetic functions are available. E, E1 and E2 stand for arbitrary arithmetic expressions.

Function | Description | Argument Types | Result Type
+ E | unary plus | number | number
– E | unary minus | number | number
abs(E) | absolute value | number | number
sgn(E) | sign value | number | integer
floor(E) | round down to integral value | number | number
ceiling(E) | round up to integral value | number | number
round(E) | round to nearest integral value | number | number
truncate(E) | truncate to integral value | number | number
E1 + E2 | addition | number × number | number
E1 – E2 | subtraction | number × number | number
E1 * E2 | multiplication | number × number | number
E1 / E2 | division | number × number | see below
E1 // E2 | integer division (truncate) | integer × integer | integer
E1 rem E2 | integer remainder | integer × integer | integer
E1 div E2 | integer division (floor) | integer × integer | integer
E1 mod E2 | integer modulus | integer × integer | integer
gcd(E1,E2) | greatest common divisor | integer × integer | integer
lcm(E1,E2) | least common multiple | integer × integer | integer
E1 ^ E2 | power operation | number × number | number
min(E1,E2) | minimum of 2 values | number × number | number
max(E1,E2) | maximum of 2 values | number × number | number
`\` E | bitwise complement | integer | integer
E1 `/\` E2 | bitwise conjunction | integer × integer | integer
E1 `\/` E2 | bitwise disjunction | integer × integer | integer
xor(E1,E2) | bitwise exclusive disjunction | integer × integer | integer
E1 >> E2 | shift E1 right by E2 bits | integer × integer | integer
E1 << E2 | shift E1 left by E2 bits | integer × integer | integer
sin(E) | trigonometric function | number | real
cos(E) | trigonometric function | number | real
tan(E) | trigonometric function | number | real
asin(E) | trigonometric function | number | real
acos(E) | trigonometric function | number | real
atan(E) | trigonometric function | number | real
atan(E1,E1) | trigonometric function | number × number | real
exp(E) | exponential function ex | number | real
ln(E) | natural logarithm | number | real
sqrt(E) | square root | number | real
pi | the constant pi = 3.1415926... | — | float
e | the constant e = 2.7182818... | — | float
fix(E) | convert to integer (truncate) | number | integer
integer(E) | convert to integer (exact) | number | integer
float(E) | convert to float | number | float
breal(E) | convert to bounded real | number | breal
rational(E) | convert to rational | number | rational
rationalize(E) | convert to rational | number | rational
numerator(E) | extract numerator of a rational | integer or rational | integer
denominator(E) | extract denominator of a rational | integer or rational | integer
sum(L) | sum of list elements | list | number
min(L) | minimum of list elements | list | number
max(L) | maximum of list elements | list | number
eval(E) | evaluate runtime expression | term | number

Argument types other than specified yield a type error. As an argument type, number stands for integer, rational, float or breal with the type conversions as specified above. As a result type, number stands for the more general of the argument types, and real stands for float or breal. The division operator / yields either a rational or a float result, depending on the value of the global flag `prefer_rationals`. The same is true for the result of ^ if an integer is raised to a negative integral power.
The integer division // rounds the result towards zero (truncates), while the div division rounds towards negative infinity (floor). Each division function is paired with a corresponding remainder function: (rem computes the remainder corresponding to //, and mod computes the remainder corresponding to div 4. The remainder results differ only in the case where the two arguments have opposite signs. The relationship between them is as follows:

>     X =:= (X rem Y) + (X // Y) * Y
>     X =:= (X mod Y) + (X div Y) * Y

This table gives an overview:

>           10 x 3   -10 x 3   10 x -3   -10 x -3

>     //       3        -3       -3          3
>     rem      1        -1        1         -1
>     div      3        -4       -4          3
>     mod      1         2       -2         -1

### 8.3.2 Evaluation Mechanism

An arithmetic expression is a Prolog term that is made up of variables, numbers, atoms and compound terms, e.g.

>     3 * 1.5 + Y / sqrt(pi)

Compound terms are evaluated by first evaluating their arguments and then calling the corresponding evaluation predicate. The evaluation predicate associated with a compound term func(a_1,..,a_n) is the predicate func/(n+1). It receives a_1,..,a_n as its first n arguments and returns a numeric result as its last argument. This result is then used in the arithmetic computation. For instance, the expression above would be evaluated by the goal sequence

>     *(3,1.5,T1), sqrt(3.14159,T2), /(Y,T2,T3), +(T1,T3,T4)

where Ti are auxiliary variables created by the system to hold intermediate results.
Although this evaluation mechanism is usually transparent to the user, it becomes visible when errors occur, when subgoals are delayed, or when inline-expanded code is traced.

### 8.3.3 User Defined Arithmetic Functions

This evaluation mechanism outlined above is not restricted to the predefined arithmetic functions shown in the table. In fact it works for all atoms and compound terms. It is therefore possible to define a new arithmetic operation by just defining an evaluating predicate:

>     [eclipse 1]: [user].
>      :- op(200, yf, !).             % let's have some syntaxtic sugar
>      !(N, F) :- fac(N, 1, F).
>      fac(0, F0, F) :- !, F=F0.
>      fac(N, F0, F) :- N1 is N-1, F1 is F0*N, fac(N1, F1, F).
>      user       compiled traceable 504 bytes in 0.00 seconds

>     yes.
>     [eclipse 2]: X is 23!.       % calls !/2

>     X = 25852016738884976640000
>     yes.

Note that this mechanism is not only useful for user-defined predicates, but can also be used to call ECLiPSe built-ins inside arithmetic expressions, eg.

>     T is cputime - T0.
>     L is string_length("abcde") - 1.

which call cputime/1 and string_length/2 respectively. Any predicate that returns a number as its last argument can be used in a similar manner.
However there is a difference compared to the evaluation of the predefined arithmetic functions (as listed in the table above): The arguments of the user-defined arithmetic expression are not evaluated but passed unchanged to the evaluating predicate. E.g. the expression `twice(3+4)` is transformed into the goal `twice(3+4, Result)` rather than `twice(7, Result)`. This makes sense because otherwise it would not be possible to pass any compound term to the predicate. If evaluation is wanted, the user-defined predicate can explicitly call is/2 or use eval/1.

### 8.3.4 Runtime Expressions

In order to enable efficient compilation of arithmetic expressions, ECLiPSe requires that variables in compiled arithmetic expressions must be bound to numbers at runtime, not symbolic expressions. E.g. in the following code p/1 will only work when called with a numerical argument, else it will raise error 24:

>     p(Number) :- Res is 1 + Number, ...

To make it work even when the argument gets bound to a symbolic expression at runtime, use eval/1 as in the following example:

>     p(Expr) :- Res is 1 + eval(Expr), ...

If the expression is the only argument of is/2, the eval/1 may be omitted.