Arithmetic

### 8.6 Arithmetic

- Evaluation of an arithmetic expression
- `(is)/2` - evaluate expression
- `(=:=)/2` - arithmetic equal, `(=``\``=)/2` - arithmetic not equal,
  `(``<``)/2` - arithmetic less than, `(=``<``)/2` - arithmetic less than or equal to,
  `(``>``)/2` - arithmetic greater than, `(``>``=)/2` - arithmetic greater than or equal to
- `succ/2`

#### 8.6.1 Evaluation of an arithmetic expression

An arithmetic expression is a Prolog term built from numbers, variables, and functors (or operators) that represent arithmetic functions. When an expression is evaluated each variable must be bound to a non-variable expression. An expression evaluates to a number, which may be an integer or a floating point number. The following table details the components of an arithmetic expression, how they are evaluated, the types expected/returned and if they are ISO or an extension:

> Expression | Result = eval(Expression) | Signature | ISO
> a variable | bound to an expression `E`, result is eval(`E`) | IF → IF | Y
> an integer number | this number | I | Y
> a floating point number | this number | F | Y
> `pi` | the value of π = 3.141592... | F | Y
> `e` | the value of e = 2.718281... | F | N
> `epsilon` | difference between 1.0 and minimum float > 1.0 | F | N
> `+ E` | eval(`E`) | IF → IF | Y
> `- E` | - eval(`E`) | IF → IF | Y
> `inc(E)` | eval(`E`) + 1 | IF → IF | N
> `dec(E)` | eval(`E`) - 1 | IF → IF | N
> `E1 + E2` | eval(`E1`) + eval(`E2`) | IF, IF → IF | Y
> `E1 - E2` | eval(`E1`) - eval(`E2`) | IF, IF → IF | Y
> `E1 * E2` | eval(`E1`) * eval(`E2`) | IF, IF → IF | Y
> `E1 / E2` | eval(`E1`) / eval(`E2`) | IF, IF → F | Y
> `E1 // E2` | rnd(eval(`E1`) / eval(`E2`)) | I, I → I | Y
> `E1 rem E2` | eval(`E1`) - (rnd(eval(`E1`) / eval(`E2`)) * eval(`E2`)) | I, I → I | Y
> `E1 div E2` | ⌊(eval(`E1`) - eval(`E1`) `mod` eval(`E2`)) / eval(`E2`)⌋ | I, I → I | Y
> `E1 mod E2` | eval(`E1`) - (⌊eval(`E1`) / eval(`E2`)⌋ * eval(`E2`)) | I, I → I | Y
> `E1 /\ E2` | eval(`E1`) bitwise_and eval(`E2`) | I, I → I | Y
> `E1 \/ E2` | eval(`E1`) bitwise_or eval(`E2`) | I, I → I | Y
> `xor(E1,E2)` | eval(`E1`) bitwise_xor eval(`E2`) | I, I → I | Y
> `\ E` | bitwise_not eval(`E`) | I → I | Y
> `E1 << E2` | eval(`E1`) integer_shift_left eval(`E2`) | I, I → I | Y
> `E1 >> E2` | eval(`E1`) integer_shift_right eval(`E2`) | I, I → I | Y
> `lsb(E)` | least significant bit (from 0) of eval(`E`) or -1 | I → I | N
> `msb(E)` | most significant bit (from 0) of eval(`E`) or -1 | I → I | N
> `popcount(E)` | number of 1-bits in eval(`E`) | I → I | N
> `abs(E)` | absolute value of eval(`E`) | IF → IF | Y
> `sign(E)` | sign of eval(`E`) (-1 if < 0, 0 if = 0, +1 if > 0) | IF → IF | Y
> `min(E1,E2)` | minimal value between eval(`E1`) and eval(`E2`) | IF, IF → ? | Y
> `max(E1,E2)` | maximal value between eval(`E1`) and eval(`E2`) | IF, IF → ? | Y
> `gcd(E1,E2)` | greatest common divisor of eval(`E1`) and eval(`E2`) | I, I → I | N
> `E1 ^ E2` | eval(`E1`) raised to the power of eval(`E2`) | IF, IF → IF | Y
> `E1 ** E2` | eval(`E1`) raised to the power of eval(`E2`) | IF, IF → F | Y
> `sqrt(E)` | square root of eval(`E`) | IF → F | Y
> `tan(E)` | tangent of eval(`E`) | IF → F | Y
> `atan(E)` | arc tangent of eval(`E`) | IF → F | Y
> `atan2(Y,X)` | principal value of arc tangent of eval(`Y`) / eval(`X`) using both signs for the quadrant | IF → F | Y
> `cos(E)` | cosine of eval(`E`) | IF → F | Y
> `acos(E)` | arc cosine of eval(`E`) | IF, IF → F | Y
> `sin(E)` | sine of eval(`E`) | IF → F | Y
> `asin(E)` | arc sine of eval(`E`) | IF → F | Y
> `tanh(E)` | hyperbolic tangent of eval(`E`) | IF → F | N
> `atanh(E)` | hyperbolic arc tangent of eval(`E`) | IF → F | N
> `cosh(E)` | hyperbolic cosine of eval(`E`) | IF → F | N
> `acosh(E)` | hyperbolic arc cosine of eval(`E`) | IF, IF → F | N
> `sinh(E)` | hyperbolic sine of eval(`E`) | IF → F | N
> `asinh(E)` | hyperbolic arc sine of eval(`E`) | IF → F | N
> `exp(E)` | e raised to the power of eval(`E`) | IF → F | Y
> `log(E)` | natural logarithm of eval(`E`) | IF → F | Y
> `log10(E)` | base 10 logarithm of eval(`E`) | IF → F | N
> `log(R, E)` | base eval(`R`) logarithm of eval(`E`) | F, IF → F | N
> `float(E)` | the floating point number equal to eval(`E`) | IF → F | Y
> `ceiling(E)` | rounds eval(`E`) upward to the nearest integer | F → I | Y
> `floor(E)` | rounds eval(`E`) downward to the nearest integer | F → I | Y
> `round(E)` | rounds eval(`E`) to the nearest integer | F → I | Y
> `truncate(E)` | the integer value of eval(`E`) | F → I | Y
> `float_fractional_part(E)` | the float equal to the fractional part of eval(`E`) | F → F | Y
> `float_integer_part(E)` | the float equal to the integer part of eval(`E`) | F → F | Y

The meaning of the signature field is as follows:

- I → I: unary function, the operand must be an integer and the result is an integer.
- F → F: unary function, the operand must be a floating point number and the result is a floating point number.
- F → I: unary function, the operand must be a floating point number and the result is an integer.
- IF → F: unary function, the operand can be an integer or a floating point number and the result is a floating point number.
- IF → IF: unary function, the operand can be an integer or a floating point number and the result has the same type as the operand.
- I, I → I: binary function: each operand must be an integer and the result is an integer.
- IF, IF → IF: binary function: each operand can be an integer or a floating point number and the result is a floating point number if at least one operand is a floating point number, an integer otherwise.
- IF, IF → ?: binary function: each operand can be an integer or a floating point number and the result has the same type as the selected operand. This is used for `min` and `max`. Note that in case of equality between an integer and a floating point number the result is an integer.

`is`, `+`, `-`, `*`, `/`, `//`, `div`, `rem`, `mod`, `/\`, `\/`, `<<`, `>>`, `**` and `^` are predefined infix operators. `+`, `-` and `\`, are predefined prefix operators (section 8.14.10).

Integer division rounding function: the integer division rounding function `rnd(X)` rounds the floating point number `X` to an integer. There are two possible definitions (depending on the target machine) for this function which differ on negative numbers:

- `rnd(X)` = integer part of `X`, e.g. `rnd(-1.5)` = `-1` (round toward 0)
- `rnd(X)` = ⌊`X`⌋, e.g. `rnd(-1.5)` = `-2` (round toward −∞)

The definition of this function determines the definition of the integer division and remainder (`(//)/2` and `(rem)/2`). It is possible to test the value (`toward_zero` or `down`) of the `integer_rounding_function` Prolog flag to determine which function being used (section 8.22.1). Since rounding toward zero is the most common case, two additional evaluable functors (`(div)/2` and `(mod)/2`) are available which consider rounding toward −∞.

Fast mathematical mode: in order to speed-up integer computations, the GNU Prolog compiler can generate faster code when invoked with the `--fast-math` option (section 4.4.3). In this mode only integer operations are allowed and a variable in an expression must be bound at evaluation time to an integer. No type checking is done.

Errors

a sub-expression `E` is a variable |  | `instantiation_error`
a sub-expression `E` is neither a number nor an evaluable functor |  | `type_error(evaluable, E)`
a sub-expression `E` is a floating point number while an integer is expected |  | `type_error(integer, E)`
a sub-expression `E` is an integer while a floating point number is expected |  | `type_error(float, E)`
a division by zero occurs |  | `evaluation_error(zero_divisor)`

Portability

Refer to the above table to determine which evaluable functors are ISO and which are GNU Prolog extensions. For efficiency reasons, GNU Prolog does not detect the following ISO arithmetic errors: `float_overflow`, `int_overflow, int_underflow`, and `undefined`.

#### 8.6.2 `(is)/2` - evaluate expression

Templates

  `is(?term, +evaluable)`

Description

`Result is Expression` succeeds if `Result` can be unified with eval(`Expression`). Refer to the evaluation of an arithmetic expression for the definition of the eval function (section 8.6.1).

`is` is a predefined infix operator (section 8.14.10).

Errors

Refer to the evaluation of an arithmetic expression for possible errors (section 8.6.1).

Portability

ISO predicate.

#### 8.6.3 `(=:=)/2` - arithmetic equal, `(=\=)/2` - arithmetic not equal,
`(<)/2` - arithmetic less than, `(=<)/2` - arithmetic less than or equal to,
`(>)/2` - arithmetic greater than, `(>=)/2` - arithmetic greater than or equal to

Templates

  `=:=(+evaluable, +evaluable)
  =\=(+evaluable, +evaluable)
  <(+evaluable, +evaluable)
  =<(+evaluable, +evaluable)
  >(+evaluable, +evaluable)
  >=(+evaluable, +evaluable)`

Description

`Expr1 =:= Expr2` succeeds if eval(`Expr1`) = eval(`Expr2`).

`Expr1 =\= Expr2` succeeds if eval(`Expr1`) ≠ eval(`Expr2`).

`Expr1 < Expr2` succeeds if eval(`Expr1`) < eval(`Expr2`).

`Expr1 =< Expr2` succeeds if eval(`Expr1`) ≤ eval(`Expr2`).

`Expr1 > Expr2` succeeds if eval(`Expr1`) > eval(`Expr2`).

`Expr1 >= Expr2` succeeds if eval(`Expr1`) ≥ eval(`Expr2`).

Refer to the evaluation of an arithmetic expression for the definition of the eval function (section 8.6.1).

`=:=`, `=\=`, `<`, `=<`, `>` and `>=` are predefined infix operators (section 8.14.10).

Errors

Refer to the evaluation of an arithmetic expression for possible errors (section 8.6.1).

Portability

ISO predicates.

#### 8.6.4 `succ/2`

Templates

  `succ(+integer, ?integer)
  succ(-integer, +integer)`

Description

`succ(X, Y)` is true iff `Y` is the successor of the non-negative integer `X`.

Errors

`X` and `Y` are both variables |  | `instantiation_error`
`X` is neither a variable nor an integer |  | `type_error(integer, X)`
`Y` is neither a variable nor an integer |  | `type_error(integer, Y)`
`X` is an integer < 0 |  | `domain_error(not_less_than_zero, X)`
`Y` is an integer < 0 |  | `domain_error(not_less_than_zero, Y)`

Portability

GNU Prolog predicate.

Copyright (C) 1999-2012 Daniel Diaz Verbatim copying and distribution of this entire article is permitted in any medium, provided this notice is preserved. More about the copyright