Ada Conformity Assessment Authority      Home Conformity Assessment   Test Suite ARGAda Standard
Annotated Ada Reference Manual (Ada 2022)Legal Information
Contents   Index   References   Search   Previous   Next 

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 : Treturn T
function "/"  (Left, Right : Treturn T
function "mod"(Left, Right : Treturn T
function "rem"(Left, Right : Treturn 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)
{AI05-0260-1} 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)].
Ramification: The above identity satisfied by signed integer division is not satisfied by modular division because of the difference in effect of negation. 
Multiplication and division operators are predefined for every specific floating point type T
function "*"(Left, Right : Treturn T
function "/"(Left, Right : Treturn 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 : Treturn 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]:
Ramification: These operators are analogous to the multiplying operators involving fixed or floating point types where root_real substitutes for the fixed or floating point type, and root_integer substitutes for Integer. Only values of the corresponding universal numeric types are implicitly convertible to these root numeric types, so these operators are really restricted to use with operands of a universal type, or the specified root numeric types. 
function "*"(Left, Right : root_realreturn root_real
function "/"(Left, Right : root_realreturn root_real
function "*"(Left : root_real; Right : root_integerreturn root_real
function "*"(Left : root_integer; Right : root_realreturn root_real
function "/"(Left : root_real; Right : root_integerreturn root_real
Multiplication and division between any two fixed point types are provided by the following two predefined operators: 
Ramification: {AI12-0005-1} Universal_fixed is the universal type for the class of fixed point types, meaning that these operators take operands of any fixed point type types (not necessarily the same) and return a result that is implicitly (or explicitly) convertible to any fixed point type. 
function "*"(Left, Right : universal_fixedreturn universal_fixed
function "/"(Left, Right : universal_fixedreturn universal_fixed

Name Resolution Rules

  {AI95-00364-01} {AI95-00420-01} 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: 
{AI05-0020-1} {AI05-0209-1} 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. 
  {AI95-00364-01} {AI95-00420-01} A corresponding requirement applies to the universal fixed-fixed division operator.
Discussion: The small of universal_fixed is infinitesimal; no loss of precision is permitted. However, fixed-fixed division is impractical to implement when an exact result is required, and multiplication will sometimes result in unanticipated overflows in such circumstances, so we require an explicit conversion to be inserted in expressions like A * B * C if A, B, and C are each of some fixed point type.
On the other hand, X := A * B; is permitted by this rule, even if X, A, and B are all of different fixed point types, since the expected type for the result of the multiplication is the type of X, which is necessarily not universal_fixed.
{AI95-00364-01} {AI95-00420-01} We have made these into Name Resolution rules to ensure that user-defined primitive fixed-fixed operators are not made unusable due to the presence of these universal fixed-fixed operators. But we do allow these operators to be used if prefixed by package Standard, so that they can be used in the definitions of user-defined operators. 
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.] 
NOTE 1   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)
NOTE 2   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 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
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

Incompatibilities With Ada 83

{AI95-00364-01} {AI95-00420-01} The universal fixed-fixed multiplying operators are now directly available (see below). Any attempt to use user-defined fixed-fixed multiplying operators will be ambiguous with the universal ones. The only way to use the user-defined operators is to fully qualify them in a prefix call. This problem was not documented during the design of Ada 95, and has been mitigated by Ada 2005. 

Extensions to Ada 83

Explicit conversion of the result of multiplying or dividing two fixed point numbers is no longer required, provided the context uniquely determines some specific fixed point result type. This is to improve support for decimal fixed point, where requiring explicit conversion on every fixed-fixed multiply or divide was felt to be inappropriate.
The type universal_fixed is covered by universal_real, so real literals and fixed point operands may be multiplied or divided directly, without any explicit conversions required.

Wording Changes from Ada 83

We have used the normal syntax for function definition rather than a tabular format. 

Incompatibilities With Ada 95

{AI95-00364-01} We have changed the resolution rules for the universal fixed-fixed multiplying operators to remove the incompatibility with Ada 83 discussed above. The solution is to hide the universal operators in some circumstances. As a result, some legal Ada 95 programs will require the insertion of an explicit conversion around a fixed-fixed multiply operator. This change is likely to catch as many bugs as it causes, since it is unlikely that the user wanted to use predefined operators when they had defined user-defined versions. 

Wording Changes from Ada 2005

{AI05-0020-1} {AI05-0209-1} Correction: Wording was added to clarify that universal_fixed "*" and "/" does not apply if an appropriate operator is declared for a partial (or incomplete) view of the designated type. Otherwise, adding a partial (or incomplete) view could make some "*" and "/" operators ambiguous.
{AI05-0260-1} Correction: The wording for the mod operator was corrected so that a result of 0 does not have to have "the sign of B" (which is impossible if B is negative). 

Contents   Index   References   Search   Previous   Next 
Ada-Europe Ada 2005 and 2012 Editions sponsored in part by Ada-Europe