The language defines the following six classes of operators. The corresponding operator symbols (except /=), and only those, can be used as designators in declarations of functions for user-defined operators. They are given in the order of increasing precedence.

logical_operator ::= and | or | xor relational_operator ::= = | /= | < | <= | > | >= binary_adding_operator ::= + | - | & unary_adding_operator ::= + | - multiplying_operator ::= * | / | mod | rem highest_precedence_operator ::= ** | abs | not

The short-circuit control forms and then and or else have the same precedence as logical operators. The membership tests in and not in have the same precedence as relational operators.

For a term, simple expression, relation, or expression, operators of higher precedence are associated with their operands before operators of lower precedence. In this case, for a sequence of operators of the same precedence level, the operators are associated in textual order from left to right; parentheses can be used to impose specific associations.

The operands of a factor, of a term, of a simple expression, or of a relation, and the operands of an expression that does not contain a short-circuit control form, are evaluated in some order that is not defined by the language (but before application of the corresponding operator). The right operand of a short-circuit control form is evaluated if and only if the left operand has a certain value (see 4.5.1).

For each form of type declaration, certain of the above operators are predefined, that is, they are implicitly declared by the type declaration. For each such implicit operator declaration, the names of the parameters are LEFT and RIGHT for binary operators; the single parameter is called RIGHT for unary adding operators and for the unary operators abs and not. The effect of the predefined operators is explained in subsections 4.5.1 through 4.5.7.

The predefined operations on integer types either yield the mathematically correct result or raise the exception NUMERIC_ERROR. A predefined operation that delivers a result of an integer type (other than universal_integer) can only raise the exception NUMERIC_ERROR if the mathematical result is not a value of the type. The predefined operations on real types yield results whose accuracy is defined in section 4.5.7. A predefined operation that delivers a result of a real type (other than universal_real) can only raise the exception NUMERIC_ERROR if the result is not within the range of the safe numbers of the type, as explained in section 4.5.7.

Examples of precedence:

not SUNNY or WARM -- same as (not SUNNY) or WARM X > 4.0 and Y > 0.0 -- same as (X > 4.0) and (Y > 0.0) -4.0*A**2 -- same as -(4.0 * (A**2)) abs(1 + A) + B -- same as (abs (1 + A)) + B Y**(-3) -- parentheses are necessary A / B * C -- same as (A/B)*C A + (B + C) -- evaluate B + C before adding it to A

**References:** designator,
expression,
factor,
implicit declaration,
in some order,
integer type,
membership test,
name,
numeric_error exception,
overloading,
and 8.7,
raising of an exception,
range,
real type,
relation,
safe number,
short-circuit control form,
and 4.5.1,
simple expression,
term,
type,
type declaration,
universal_integer type,
universal_real type.

**Rationale references:**
3.6 Expressions,
3.8 Assignment Statements - The Ada Model of Time,
3.10 Short-Circuit Control Forms

**Style Guide references:**
2.1.1 Horizontal Spacing,
2.1.3 Alignment of Operators,
5.5.3 Parenthetical Expressions,
5.7.1 The Use Clause,
5.7.2 The Renames Clause,
5.7.4 Overloaded Operators,
7.2.7 Subexpression Evaluation

**Sub-topics:**

- 4.5.1 Logical Operators and Short-circuit Control Forms
- 4.5.2 Relational Operators and Membership Tests
- 4.5.3 Binary Adding Operators
- 4.5.4 Unary Adding Operators
- 4.5.5 Multiplying Operators
- 4.5.6 Highest Precedence Operators
- 4.5.7 Accuracy of Operations with Real Operands

The following logical operators are predefined for any boolean type and any one-dimensional array type whose components are of a boolean type; in either case the two operands have the same type.

Operator Operation Operand type Result typeand conjunction any boolean type same boolean type array of boolean components same array type or inclusive disjunction any boolean type same boolean type array of boolean components same array type xor exclusive disjunction any boolean type same boolean type array of boolean components same array type

The operations on arrays are performed on a component-by-component basis on matching components, if any (as for equality, see 4.5.2). The bounds of the resulting array are those of the left operand. A check is made that for each component of the left operand there is a matching component of the right operand, and vice versa. The exception CONSTRAINT_ERROR is raised if this check fails.

The short-circuit control forms and then and or else are defined for two operands of a boolean type and deliver a result of the same type. The left operand of a short-circuit control form is always evaluated first. If the left operand of an expression with the control form and then evaluates to FALSE, the right operand is not evaluated and the value of the expression is FALSE. If the left operand of an expression with the control form or else evaluates to TRUE, the right operand is not evaluated and the value of the expression is TRUE. If both operands are evaluated, and then delivers the same result as and, and or else delivers the same result as or.

Note:

The conventional meaning of the logical operators is given by the fol- lowing truth table:

A B (A and B) (A or B) (A xor B) TRUE TRUE TRUE TRUE FALSE TRUE FALSE FALSE TRUE TRUE FALSE TRUE FALSE TRUE TRUE FALSE FALSE FALSE FALSE FALSE

Examples of logical operators:

SUNNY or WARM FILTER(1 .. 10) and FILTER(15 .. 24) -- see 3.6.1

Examples of short-circuit control forms:

NEXT_CAR.OWNER /= null and then NEXT_CAR.OWNER.AGE > 25 -- see 3.8.1 N = 0 or else A(N) = HIT_VALUE

**References:** array type,
boolean type,
bound of an index range,
component of an array,
constraint_error exception,
dimension,
false boolean value,
index subtype,
matching components of arrays,
null array,
operation,
operator,
predefined operator,
raising of exceptions,
true boolean value,
type.

**Style Guide references:**
5.5.4 Positive Forms of Logic,
5.5.5 Short Circuit Forms of the Logical Operators

The equality and inequality operators are predefined for any type that is not limited. The other relational operators are the ordering operators < (less than), <= (less than or equal), > (greater than), and >= (greater than or equal). The ordering operators are predefined for any scalar type, and for any discrete array type, that is, a one-dimensional array type whose components are of a discrete type. The operands of each predefined relational operator have the same type. The result type is the predefined type BOOLEAN.

The relational operators have their conventional meaning: the result is equal to TRUE if the corresponding relation is satisfied; the result is FALSE otherwise. The inequality operator gives the complementary result to the equality operator: FALSE if equal, TRUE if not equal.

Operator Operation Operand type Result type = /= equality and inequality any type BOOLEAN < <= > >= test for ordering any scalar type BOOLEAN discrete array type BOOLEANEquality for the discrete types is equality of the values. For real operands whose values are nearly equal, the results of the predefined relational operators are given in section 4.5.7. Two access values are equal either if they designate the same object, or if both are equal to the null value of the access type.

For two array values or two record values of the same type, the left operand is equal to the right operand if and only if for each component of the left operand there is a matching component of the right operand and vice versa; and the values of matching components are equal, as given by the predefined equality operator for the component type. In particular, two null arrays of the same type are always equal; two null records of the same type are always equal.

For comparing two records of the same type, matching components are those which have the same component identifier.

For comparing two one-dimensional arrays of the same type, matching components are those (if any) whose index values match in the following sense: the lower bounds of the index ranges are defined to match, and the successors of matching indices are defined to match. For comparing two multidimensional arrays, matching components are those whose index values match in successive index positions.

If equality is explicitly defined for a limited type, it does not extend to composite types having subcomponents of the limited type (explicit definition of equality is allowed for such composite types).

The ordering operators <, <=, >, and >= that are defined for discrete array types correspond to lexicographic order using the predefined order relation of the component type. A null array is lexicographically less than any array having at least one component. In the case of nonnull arrays, the left operand is lexicographically less than the right operand if the first component of the left operand is less than that of the right; otherwise the left operand is lexicographically less than the right operand only if their first components are equal and the tail of the left operand is lexicographically less than that of the right (the tail consists of the remaining components beyond the first and can be null).

The membership tests in and not in are predefined for all types. The result type is the predefined type BOOLEAN. For a membership test with a range, the simple expression and the bounds of the range must be of the same scalar type; for a membership test with a type mark, the type of the simple expression must be the base type of the type mark. The evaluation of the membership test in yields the result TRUE if the value of the simple expression is within the given range, or if this value belongs to the subtype denoted by the given type mark; otherwise this evaluation yields the result FALSE (for a value of a real type, see 4.5.7). The membership test not in gives the complementary result to the membership test in.

Examples:

X /= Y "" < "A" and "A" < "AA" -- TRUE "AA" < "B" and "A" < "A " -- TRUE MY_CAR = null -- true if MY_CAR has been set to null (see 3.8.1) MY_CAR = YOUR_CAR -- true if we both share the same car MY_CAR.all = YOUR_CAR.all -- true if the two cars are identical N not in 1 .. 10 -- range membership test TODAY in MON .. FRI -- range membership test TODAY in WEEKDAY -- subtype membership test (see 3.5.1) ARCHIVE in DISK_UNIT -- subtype membership test (see 3.7.3)

Notes:

No exception is ever raised by a predefined relational operator or by a membership test, but an exception can be raised by the evaluation of the operands.

If a record type has components that depend on discriminants, two values of this type have matching components if and only if their discriminants are equal. Two nonnull arrays have matching components if and only if the value of the attribute LENGTH(N) for each index position N is the same for both.

**References:** access value,
array type,
base type,
belong to a subtype,
boolean predefined type,
bound of a range,
component,
component identifier,
component type,
composite type,
designate,
dimension,
discrete type,
evaluation,
exception,
index,
index range,
limited type,
null access value,
null array,
null record,
object,
operation,
operator,
predefined operator,
raising of exceptions,
range,
record type,
scalar type,
simple expression,
subcomponent,
successor,
type,
type mark.

**Style Guide references:**
2.1.1 Horizontal Spacing,
5.5.6 Accuracy of Operations With Real Operands,
5.7.5 Overloading the Equality Operator,
7.2.8 Relational Tests

The binary adding operators + and - are predefined for any numeric type and have their conventional meaning. The catenation operators & are predefined for any one-dimensional array type that is not limited.

Operator Operation Left operand type Right operand type Result type + addition any numeric type same numeric type same numeric type - subtraction any numeric type same numeric type same numeric type & catenation any array type same array type same array type any array type the component type same array type the component type any array type same array type the component type the component type any array type

For real types, the accuracy of the result is determined by the operand type (see 4.5.7).

If both operands are one-dimensional arrays, the result of the catenation is a one-dimensional array whose length is the sum of the lengths of its operands, and whose components comprise the components of the left operand followed by the components of the right operand. The lower bound of this result is the lower bound of the left operand, unless the left operand is a null array, in which case the result of the catenation is the right operand.

If either operand is of the component type of an array type, the result of the catenation is given by the above rules, using in place of this operand an array having this operand as its only component and having the lower bound of the index subtype of the array type as its lower bound.

The exception CONSTRAINT_ERROR is raised by catenation if the upper bound of the result exceeds the range of the index subtype, unless the result is a null array. This exception is also raised if any operand is of the component type but has a value that does not belong to the component subtype.

Examples:

Z + 0.1 -- Z must be of a real type "A" & "BCD" -- catenation of two string literals 'A' & "BCD" -- catenation of a character literal and a string literal 'A' & 'A' -- catenation of two character literals

**References:** array type,
character literal,
component type,
constraint_error exception,
dimension,
index subtype,
length of an array,
limited type,
null array,
numeric type,
operation,
operator,
predefined operator,
raising of exceptions,
range of an index subtype,
real type,
string literal,
type.

**Style Guide references:**
2.1.1 Horizontal Spacing,
5.7.4 Overloaded Operators

The unary adding operators + and - are predefined for any numeric type and have their conventional meaning. For each of these operators, the operand and the result have the same type.

Operator Operation Operand type Result type + identity any numeric type same numeric type - negation any numeric type same numeric type

**References:** numeric type,
operation,
operator,
predefined operator,
type.

The operators * and / are predefined for any integer and any floating point type and have their conventional meaning; the operators mod and rem are predefined for any integer type. For each of these operators, the operands and the result have the same base type. For floating point types, the accuracy of the result is determined by the operand type (see 4.5.7).

Operator Operation Operand type Result type * multiplication any integer type same integer type any floating point same floating point type type / integer division any integer type same integer type floating division any floating point same floating point type type mod modulus any integer type same integer type rem remainder any integer type same integer type

Integer division and remainder are defined by the relation

A = (A/B)*B + (A rem B)

where (A rem B) has the sign of A and an absolute value less than the absolute value of B. Integer division satisfies the identity

(-A)/B = -(A/B) = A/(-B)

The result of the modulus operation is such that (A mod B) has the sign of B and an absolute value less than the absolute value of B; in addition, for some integer value N, this result must satisfy the relation

A = B*N + (A mod B)

For each fixed point type, the following multiplication and division operators, with an operand of the predefined type INTEGER, are predefined.

Operator Operation Left operand Right operand Result type type type * multiply any fixed point INTEGER same as left type INTEGER any fixed point same as right type / division any fixed point INTEGER same as left typeInteger multiplication of fixed point values is equivalent to repeated addition. Division of a fixed point value by an integer does not involve a change in type but is approximate (see 4.5.7).

Finally, the following multiplication and division operators are declared in the predefined package STANDARD. These two special operators apply to operands of all fixed point types (it is a consequence of other rules that they cannot be renamed or given as generic actual parameters).

Operator Operation Left operand Right operand Result type type type * multiply any fixed point any fixed point universal_fixed type type / divide any fixed point any fixed point universal_fixed type type

Multiplication of operands of the same or of different fixed point types is exact and delivers a result of the anonymous predefined fixed point type universal_fixed whose delta is arbitrarily small. The result of any such multiplication must always be explicitly converted to some numeric type. This ensures explicit control of the accuracy of the computation. The same considerations apply to division of a fixed point value by another fixed point value. No other operators are defined for the type universal_fixed.

The exception NUMERIC_ERROR is raised by integer division, rem, and mod if the right operand is zero.

Examples:

I : INTEGER := 1; J : INTEGER := 2; K : INTEGER := 3; X : REAL digits 6 := 1.0; -- see 3.5.7 Y : REAL digits 6 := 2.0; F : FRACTION delta 0.0001 := 0.1; -- see 3.5.9 G : FRACTION delta 0.0001 := 0.1; Expression Value Result Type I*J 2 same as I and J, that is, INTEGER K/J 1 same as K and J, that is, INTEGER K mod J 1 same as K and J, that is, INTEGER X/Y 0.5 same as X and Y, that is, REAL F/2 0.05 same as F, that is, FRACTION 3*F 0.3 same as F, that is, FRACTION F*G 0.01 universal_fixed, conversion needed FRACTION(F*G) 0.01 FRACTION, as stated by the conversion REAL(J)*Y 4.0 REAL, the type of both operands after conversion of J

Notes:

For positive A and B, A/B is the quotient and A rem B is the remainder when A is divided by B. The following relations are satisfied by the rem operator:

A rem (-B) = A rem B (-A) rem B = -(A rem B)

For any integer K, the following identity holds:

A mod B = (A + K*B) mod B

The relations between integer division, remainder, and modulus are illustrated by the following table:

A B A/B A rem B A mod B A B A/B A rem B A mod B 10 5 2 0 0 -10 5 -2 0 0 11 5 2 1 1 -11 5 -2 -1 4 12 5 2 2 2 -12 5 -2 -2 3 13 5 2 3 3 -13 5 -2 -3 2 14 5 2 4 4 -14 5 -2 -4 1 10 -5 -2 0 0 -10 -5 2 0 8 11 -5 -2 1 -4 -11 -5 2 -1 -1 12 -5 -2 2 -3 -12 -5 2 -2 -2 13 -5 -2 3 -2 -13 -5 2 -3 -3 14 -5 -2 4 -1 -14 -5 2 -4 -4

**References:** actual parameter,
base type,
declaration,
delta of a fixed point type,
fixed point type,
floating point type,
generic formal subprogram,
integer type,
numeric type,
numeric_error exception,
predefined operator,
raising of exceptions,
renaming declaration,
standard predefined package,
type conversion.

**Style Guide references:**
9.1.5 Constraint Checking

The highest precedence unary operator abs is predefined for any numeric type. The highest precedence unary operator not is predefined for any boolean type and any one-dimensional array type whose components have a boolean type.

Operator Operation Operand type Result type abs absolute value any numeric type same numeric type not logical negation any boolean type same boolean type array of boolean components same array type

The operator not that applies to a one-dimensional array of boolean components yields a one-dimensional boolean array with the same bounds; each component of the result is obtained by logical negation of the corresponding component of the operand (that is, the component that has the same index value).

The highest precedence exponentiating operator ** is predefined for each integer type and for each floating point type. In either case the right operand, called the exponent, is of the predefined type INTEGER.

Operator Operation Left operand Right operand Result type type type ** exponentiation any integer type INTEGER same as left any floating point INTEGER same as left type

Exponentiation with a positive exponent is equivalent to repeated multiplication of the left operand by itself, as indicated by the exponent and from left to right. For an operand of a floating point type, the exponent can be negative, in which case the value is the reciprocal of the value with the positive exponent. Exponentiation by a zero exponent delivers the value one. Exponentiation of a value of a floating point type is approximate (see 4.5.7). Exponentiation of an integer raises the exception CONSTRAINT_ERROR for a negative exponent.

**References:** array type,
boolean type,
bound of an array,
component of an array,
constraint_error exception,
dimensionality,
floating point type,
index,
integer type,
multiplication operation,
predefined operator,
raising of exceptions.

**Style Guide references:**
5.5.3 Parenthetical Expressions

A real subtype specifies a set of model numbers. Both the accuracy required from any basic or predefined operation giving a real result, and the result of any predefined relation between real operands are defined in terms of these model numbers.

A model interval of a subtype is any interval whose bounds are model numbers of the subtype. The model interval associated with a value that belongs to a real subtype is the smallest model interval (of the subtype) that includes the value. (The model interval associated with a model number of a subtype consists of that number only.)

For any basic operation or predefined operator that yields a result of a real subtype, the required bounds on the result are given by a model interval defined as follows:

- The result model interval is the smallest model interval (of the
result subtype) that includes the minimum and the maximum of all the
values obtained by applying the (exact) mathematical operation, when
each operand is given any value of the model interval (of the operand
subtype) defined for the operand.

- The model interval of an operand that is itself the result of an
operation, other than an implicit conversion, is the result model
interval of this operation.

- The model interval of an operand whose value is obtained by implicit conversion of a universal expression is the model interval associated with this value within the operand subtype.

The result model interval is undefined if the absolute value of one of the above mathematical results exceeds the largest safe number of the result type. Whenever the result model interval is undefined, it is highly desirable that the exception NUMERIC_ERROR be raised if the implementation cannot produce an actual result that is in the range of safe numbers. This is, however, not required by the language rules, in recognition of the fact that certain target machines do not permit easy detection of overflow situations. The value of the attribute MACHINE_OVERFLOWS indicates whether the target machine raises the exception NUMERIC_ERROR in overflow situations (see 13.7.3).

The safe numbers of a real type are defined (see 3.5.6) as a superset of the model numbers, for which error bounds follow the same rules as for model numbers. Any definition given in this section in terms of model intervals can therefore be extended to safe intervals of safe numbers. A consequence of this extension is that an implementation is not allowed to raise the exception NUMERIC_ERROR when the result interval is a safe interval.

For the result of exponentiation, the model interval defining the bounds on the result is obtained by applying the above rules to the sequence of multiplications defined by the exponent, and to the final division in the case of a negative exponent.

For the result of a relation between two real operands, consider for each operand the model interval (of the operand subtype) defined for the operand; the result can be any value obtained by applying the mathematical comparison to values arbitrarily chosen in the corresponding operand model intervals. If either or both of the operand model intervals is undefined (and if neither of the operand evaluations raises an exception) then the result of the comparison is allowed to be any possible value (that is, either TRUE or FALSE).

The result of a membership test is defined in terms of comparisons of the operand value with the lower and upper bounds of the given range or type mark (the usual rules apply to these comparisons).

Note:

For a floating point type the numbers 15.0, 3.0, and 5.0 are always model numbers. Hence X/Y where X equals 15.0 and Y equals 3.0 yields exactly 5.0 according to the above rules. In the general case, division does not yield model numbers and in consequence one cannot assume that (1.0/X)*X = 1.0.

**References:** attribute,
basic operation,
bound of a range,
error bound,
exponentiation operation,
false boolean value,
floating point type,
machine_overflows attribute,
membership test,
model number,
multiplication operation,
numeric_error exception,
predefined operation,
raising of exceptions,
range,
real type,
relation,
relational operator,
and 4.5,
safe number,
subtype,
true boolean value,
type conversion,
type mark,
universal expression,
and 4.

**Style Guide references:**
5.5.6 Accuracy of Operations With Real Operands,
7.2.2 Ada Model,
7.2.3 Analysis,
7.2.4 Accuracy Constraints,
7.2.5 Comments,
7.2.7 Subexpression Evaluation

Address any questions or comments to adainfo@sw-eng.falls-church.va.us.