Arithmetic and arithmetic expressions
Arithmetic operations are performed by combining arithmetic expressions, such as X + 1, with evaluable predicates, such as the evaluation predicate, is/2, or the arithmetic comparison predicate, =</2.
An arithmetic expression is a Prolog term. Arity/Prolog32 provides operator definitions for the common arithmetic operators. The following are equivalent:
'+'(2, 1)
2 + 1
Operator definitions do not affect the evaluation of arithmetic expressions. They merely simplify the input and output of these expressions. Operator definitions are discussed in more detail in the chapter about input and output.
Remember that an arithmetic expression is just a Prolog term and is not evaluated and the result is not computed until the expression appears as an argument to an arithmetic evaluable predicate. A common error is to write something like X = 2 + 3 expecting X to be evaluated to 5. In fact, X becomes instantiated with the term '+'(2,3).
Arithmetic evaluation
Arity/Prolog32 has an integrated approach to the processing of integer and floating point numbers. Whenever a numeric result of a read or a computation (including the is/2 predicate and embedded C calls) is returned to Prolog, it is checked to see if it can be exactly represented as a signed 32-bit integer. If so, it is represented internally as an integer, if not, it is represented internally as a IEEE 754 double precision (64-bit) float. The implications of this are the following:
- Less space is consumed on the stacks and in the database.
- Calculations using the is/2 predicate and other arithmetic predicates is consistent with expectations.
- Unification of numbers is more consistent (but be wary of matching two floats because two floats that appear to be the same when written may have different low precision bits).
- The float/1 predicate succeeds for arguments that are numbers that cannot be represented as a signed 32-bit integer.
- The integer/1 predicate succeeds for arguments that are numbers that can be represented as a signed 32-bit integer.
- The number/1 predicate succeeds for any numeric argument.
- The float_text/3 predicate now will accept integers as well as floats as its first argument.
- The write and display predicates output a number as an integer whenever that number is may be represented as a signed 32-bit integer and otherwise will output a number in general floating point format.
Arithmetic expressions
The arithmetic operators described below can appear in arithmetic expressions. Except where noted, the letters X and Y represent any expression, integer, floating-point number, or one of the following constants:
random
Wherever random appears in an expression, a random number between 0 and 1 is substituted for the constant.
pi
Wherever the pi constant appears, the value of pi to 15 decimal places is substituted in the expression.
err
Any computations involving the atom err results in err. Any computation that generates an underflow or overflow condition or that is the result of an operation where an argument is not in the domain (such as a float applied to a bitwise function) results in err. If an arithmetic expression is not a ground term then the result is err.
The following are the Arity/Prolog32 arithmetic expression operators:
Form | Meaning |
---|---|
X + Y | Addition |
X – Y | Subtraction |
X * X | Multiplication |
X / Y | Ordinary division |
X // Y | Integer division - result is an integer |
X ^ Y | Exponentiation |
-X | Unary minus (negates X) |
X mod Y | Returns the remainder of X divided by Y |
abs(X) | Absolute value of X |
acos(X) | Arc cosine of X |
asin(X) | Arc sine of X |
atan(X) | Arc tangent of X |
cos(X) | Cosine of X |
exp(X) | e raised to the value of X |
float(X) | Returns X unchanged (provided for compatibility) |
integer(X) | The fractional part of X is truncated returning an integer |
ln(X) | Logarithm base e of X |
log(X) | Logarithm base 10 of X |
sin(X) | Sin of X |
sqrt(X) | Square root of X |
tan(X) | Tangent of X |
round(X, N) | X rounded to N decimal places; N is an integer (0 to 15) |
The following are the Arity/Prolog32 bitwise expression operators:
Form | Meaning |
---|---|
X /\ Y | Bitwise conjunction (AND) (integers only) |
X \/ Y | Bitwise disjunction (OR) (integers only) |
X \+/ Y | Bitwise exclusive - or (XOR) (integers only) |
\(X) | Bitwise negation (NOT) (integers only) |
X << Y | Bitwise shift X left by Y places (integers only) |
X >> Y | Bitwise shift X right by Y places (integers only) |
The following are the Arity/Prolog32 logical expression operators whose value is 0 or 1 based on the logical interpretations of their arguments 0 or non-zero:
Form | Meaning |
---|---|
X and Y | Logical and |
X or Y | Logical or |
not(X) | Logical not |
The following are the Arity/Prolog32 comparison whose value is 0 or 1 based on the value of the comparison:
Form | Meaning |
---|---|
X =:= Y | Equality |
X =\= Y | Inequality |
X >= Y | Greater than or equal |
X =< Y | Less than or equal |
X > Y | Greater than |
X < Y | Less than |
The following are Arity/Prolog32 special functions:
Form | Meaning |
---|---|
[X] | Evaluates to X |
min/N | Evaluates to the minimum value of the evaluated arguments. The number of arguments must be between 1 and 255. |
max/N | Evaluates to the maximum value of the evaluated arguments. The number of arguments must be between 1 and 255. |
ifthenelse/3 | Evaluates to the value of the 2nd argument's expression or the 3rd argument's expression based on the value of the 1st argument's expression being non-zero or 0. |
Arithmetic predicates
The following are the arithmetic evaluable predicates. E1 and E2 represent valid arithmetic expressions.
Evaluation predicates:
X is E1
Evaluates E1 and unifies the value with X.
inc(+X, -Y)
Increments X and returns the value to Y. (integers only)
dec(+X, -Y)
Decrements X and returns the value to Y. (integers only)
Comparison predicates (always fail if either E1 or E2 evaluates to err):
E1 =:= E2
Evaluates E1 and E2 and suceeds if the results are equivalent.
E1 =\= E2
Evaluates E1 and E2 and suceeds if the results are equivalent.
E1 > E2
Succeeds if the value of E1 is greater than E2.
E1 < E2
Succeeds if the value of E1 is less than E2.
E1 >= E2
Succeeds if the value of E1 is greater than or equal to E2.
E1 =< E2
Succeeds if the value of E1 is less than or equal to E2.
The random number generator may be reset using the following predicate:
randomize(+Seed)
Resets the random number generator. The Seed argument is an integer you supply.
Counter predicates
Prolog programmers sometimes find that it is convenient to store, increment, decrement, and look up integer values without passing those values as arguments throughout their code. A common use is to count the number of occurrences of a particular event, such as the number of lines of input read. Another common use is to remember state information, particularly for error checking and exceptions processing. Because these counters are available throughout the program, you can use them in repeat-fail loops rather than in recursive predicates.
Arity/Prolog32 provides predicates for such counters. There are two kinds of counters provided:
- Global counters, numbered from 0 to 31. These may be accessed anywhere in your program, process-wide.
- Local counters, numbered from 32 to 63. These are allocated for each thread separately.
The following are the counter predicates supplied by Arity/Prolog32.
ctr_set(+Counter, +Value)
Sets a counter to the number you desire.
ctr_dec(+Counter, -Value)
Decrements a counter and returns the counter's previous value.
ctr_inc(+Counter, -Value)
Increments the counter and returns the counter's previous value.
ctr_is(+Counter, -Value)
Returns the current value of a counter.
Bit predicates
The following predicates are useful for using integers to store information in individual bits. These predicates allow you to set the value of a bit, get the value of a bit, apply a mask to a set of bits or simply find out how many bits are set in an integer. You may use all of the 32 bits stored in an integer. The bits are numbered from 0 to 31.
bit_lit(+Bit, +Integer)
Succeeds if the specified Bit has the value 1 in Integer.
For example:
?- bit_lit(0, 4).
no
?- bit_lit(0, 5).
yes
bit_unlit(+Bit, +Integer)
Succeeds if the specified Bit has the value 0 in Integer.
For example:
?- bit_unlit(0,5).
no
?- bit_unlit(0,4).
yes
get_bit(+Bit, +Integer, -Value)
The get_bit/3 predicate returns the Value (either 0 or 1) of the specified Bit in Integer.
For example:
?- get_bit(2, 5, X).
X=1
yes
?- get_bit(1,5,X).
X=0
yes
set_bit(+Bit, +NewValue, +OldInteger, -NewInteger, -OldValue)
The set_bit/5 predicate is used to both set and get the Value for a Bit in an Integer.
For example, you can set the second bit(1) in integer 5 to 1 with the following query:
?- set_bit(1,1,5,X,Y).
X=7
Y=0
yes
bit_count(+Integer, -Count)
The bit_count/2 predicate can be used to return the Count of bits in Integer that are currently set to 1.
For example:
?- bit_count(5,X).
X=2
yes
set_bits(+OldInteger, +Mask, +Data, -NewInteger)
The set_bits/4 predicate is used to set the values of multiple bits in an Integer at the same time. Mask defines which bits are being changed. Each bit in Mask that is set to the value 1 will be set to the value in the same position in the Data argument.
For example, if you want to set bit 1 to 1 and bit 0 to 0 in the number 5 you would do the following:
?- set_bits(5,3,2,X).
X=6
yes