4.5.5 Multiplying Operators
Static Semantics
The
multiplying operators * (multiplication), / (division),
mod (modulus),
and
rem (remainder) are predefined for every specific integer
type
T:
function "*" (Left, Right : T) return T
function "/" (Left, Right : T) return T
function "mod"(Left, Right : T) return T
function "rem"(Left, Right : T) return T
Signed integer multiplication has its conventional
meaning.
Signed 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. Signed integer division satisfies the identity:
(-A)/B = -(A/B) = A/(-B)
The signed integer
modulus operator is defined such that the result of A mod B is
either zero, or has the sign of B and an absolute value less than the
absolute value of B; in addition, for some signed integer value N, this
result satisfies the relation:
A = B*N + (A mod B)
The multiplying operators on modular types are
defined in terms of the corresponding signed integer operators, followed
by a reduction modulo the modulus if the result is outside the base range
of the type (which is only possible for the "*" operator).
Multiplication and
division operators are predefined for every specific floating point type
T:
function "*"(Left, Right : T) return T
function "/"(Left, Right : T) return T
The following multiplication
and division operators, with an operand of the predefined type Integer,
are predefined for every specific fixed point type T:
function "*"(Left : T; Right : Integer) return T
function "*"(Left : Integer; Right : T) return T
function "/"(Left : T; Right : Integer) return T
All of the above multiplying
operators are usable with an operand of an appropriate universal numeric
type. The following additional multiplying operators for
root_real
are predefined, and are usable when both operands are of an appropriate
universal or root numeric type, and the result is allowed to be of type
root_real, as in a
number_declaration:
function "*"(Left, Right : root_real) return root_real
function "/"(Left, Right : root_real) return root_real
function "*"(Left : root_real; Right : root_integer) return root_real
function "*"(Left : root_integer; Right : root_real) return root_real
function "/"(Left : root_real; Right : root_integer) return root_real
Multiplication and
division between any two fixed point types are provided by the following
two predefined operators:
function "*"(Left, Right : universal_fixed) return universal_fixed
function "/"(Left, Right : universal_fixed) return universal_fixed
Name Resolution Rules
The above two fixed-fixed
multiplying operators shall not be used in a context where the expected
type for the result is itself
universal_fixed — the context
has to identify some other numeric type to which the result is to be
converted, either explicitly or implicitly. Unless the predefined universal
operator is identified using an expanded name with
prefix
denoting the package Standard, an explicit conversion is required on
the result when using the above fixed-fixed multiplication operator if
either operand is of a type having a user-defined primitive multiplication
operator such that:
it is declared immediately within the same declaration
list as the type or any partial or incomplete view thereof; and
both of its formal parameters are of a fixed-point
type.
A corresponding requirement applies to the universal
fixed-fixed division operator.
Paragraph 20 was
deleted.
Dynamic Semantics
The multiplication and division operators for real
types have their conventional meaning. For floating point types, the
accuracy of the result is determined by the precision of the result type.
For decimal fixed point types, the result is truncated toward zero if
the mathematical result is between two multiples of the
small
of the specific result type (possibly determined by context); for ordinary
fixed point types, if the mathematical result is between two multiples
of the
small, it is unspecified which of the two is the result.
The
exception Constraint_Error is raised by integer division,
rem,
and
mod if the right operand is zero. Similarly, for a real type
T with
T'Machine_Overflows True, division by zero raises
Constraint_Error.
17 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)
18 For any
signed integer K, the following identity holds:
A mod B = (A + K*B) mod B
The relations between
signed 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
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 -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
Examples
Examples of expressions
involving multiplying operators:
I : Integer := 1;
J : Integer := 2;
K : Integer := 3;
X : Real := 1.0; --
see 3.5.7
Y : Real := 2.0;
F : Fraction := 0.25; --
see 3.5.9
G : Fraction := 0.5;
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.125 same as F, that is, Fraction
3*F 0.75 same as F, that is, Fraction
0.75*G 0.375 universal_fixed, implicitly convertible
to any fixed point type
Fraction(F*G) 0.125 Fraction, as stated by the conversion
Real(J)*Y 4.0 Real, the type of both operands after
conversion of J
Ada 2005 and 2012 Editions sponsored in part by Ada-Europe