G.2.3 Model of Fixed Point Arithmetic
In the strict mode, the predefined arithmetic operations
of a fixed point type shall satisfy the accuracy requirements specified
here and shall avoid or signal overflow in the situations described.
Implementation Requirements
The accuracy requirements for the predefined fixed
point arithmetic operations and conversions, and the results of relations
on fixed point operands, are given below.
Discussion: This subclause does not cover
the accuracy of an operation of a static expression; such operations
have to be evaluated exactly (see
4.9).
The operands of the fixed point adding operators,
absolute value, and comparisons have the same type. These operations
are required to yield exact results, unless they overflow.
Multiplications and divisions are allowed between
operands of any two fixed point types; the result has to be (implicitly
or explicitly) converted to some other numeric type. For purposes of
defining the accuracy rules, the multiplication or division and the conversion
are treated as a single operation whose accuracy depends on three types
(those of the operands and the result). For decimal fixed point types,
the attribute T'Round may be used to imply explicit conversion with rounding
(see
3.5.10).
When the result type is a floating point type, the
accuracy is as given in
G.2.1.
For
some combinations of the operand and result types in the remaining cases,
the result is required to belong to a small set of values called the
perfect result set;
for other combinations,
it is required merely to belong to a generally larger and implementation-defined
set of values called the
close result set. When the result type
is a decimal fixed point type, the perfect result set contains a single
value; thus, operations on decimal types are always fully specified.
Implementation defined: The definition
of close result set, which determines the accuracy of certain
fixed point multiplications and divisions.
{
AI12-0453-1}
When one operand of a fixed-fixed multiplication or division is of type
universal_real, that operand is not implicitly converted in the
usual sense, since the context does not determine a unique target type,
but the accuracy of the result of the multiplication or division (that
is, whether the result has to belong to the perfect result set or merely
the close result set) depends on the value of the operand of type
universal_real
and on the types of the other operand and of the result.
Discussion: {
AI12-0453-1}
We need not consider here the multiplication or division of two such
operands, since in that case either the operation is evaluated exactly
(that is, it is an operation of a static expression all of whose operators
are of a root numeric type) or it is considered to be an operation of
a floating point type.
For a fixed point multiplication
or division whose (exact) mathematical result is v,
and for the conversion of a value v
to a fixed point type, the perfect result set and close result set are
defined as follows:
If the result type
is an ordinary fixed point type with a small of s,
if v
is an integer multiple of s, then the
perfect result set contains only the value v;
otherwise, it contains the integer
multiple of s just below v
and the integer multiple of s just
above v.
The close result set is an implementation-defined
set of consecutive integer multiples of s
containing the perfect result set as a subset.
If the result type
is a decimal type with a small of s,
if v
is an integer multiple of s, then the
perfect result set contains only the value v;
{
AI05-0264-1}
otherwise, if truncation applies, then it contains only the integer multiple
of
s in the direction toward zero,
whereas if rounding applies, then it contains only the nearest integer
multiple of
s (with ties broken by
rounding away from zero).
The close result set is an implementation-defined
set of consecutive integer multiples of s
containing the perfect result set as a subset.
Ramification: As a consequence of subsequent
rules, this case does not arise when the operand types are also decimal
types.
If the result type
is an integer type,
if v
is an integer, then the perfect result set contains only the value v;
otherwise, it contains the integer
nearest to the value v (if v
lies equally distant from two consecutive integers, the perfect result
set contains the one that is further from zero).
The close result set is an implementation-defined
set of consecutive integers containing the perfect result set as a subset.
{
AI12-0453-1}
The result of a fixed point multiplication or division shall belong either
to the perfect result set or to the close result set, as described below,
if overflow does not occur. In the following cases, if the result type
is a fixed point type, let
s be its
small; otherwise, that is when the result type is an integer type,
let
s be 1.0.
{
AI12-0453-1}
For a multiplication or division neither of whose operands is of type
universal_real, let
l and
r
be the
smalls of the left and right operands. For a multiplication,
if (
l ·
r) /
s
is an integer or the reciprocal of an integer (the
smalls are
said to be “compatible” in this case), the result shall belong
to the perfect result set; otherwise, it belongs to the close result
set. For a division, if
l / (
r ·
s)
is an integer or the reciprocal of an integer (that is, the
smalls
are compatible), the result shall belong to the perfect result set; otherwise,
it belongs to the close result set.
Ramification: When the operand and result
types are all decimal types, their smalls are necessarily compatible;
the same is true when they are all ordinary fixed point types with binary
smalls.
For a multiplication or division having one universal_real
operand with a value of v, note that
it is always possible to factor v as
an integer multiple of a “compatible” small, but the
integer multiple may be “too big”. If there exists a factorization
in which that multiple is less than some implementation-defined limit,
the result shall belong to the perfect result set; otherwise, it belongs
to the close result set.
Implementation defined: Conditions on
a universal_real operand of a fixed point multiplication or division
for which the result shall be in the perfect result set.
{
AI12-0300-1}
A multiplication P * Q of an operand of a fixed point type F by an operand
of type Integer, or vice versa, and a division P / Q of an operand of
a fixed point type F by an operand of type Integer, are also allowed.
In these cases, the result has the type of F; explicit conversion of
the result is never required. The accuracy required in these cases is
the same as that required for a multiplication F(P * Q) or a division
F(P / Q) obtained by interpreting the operand of the integer type to
have a fixed point type with a
small of 1.0.
The accuracy of the result of a conversion from an
integer or fixed point type to a fixed point type, or from a fixed point
type to an integer type, is the same as that of a fixed point multiplication
of the source value by a fixed point operand having a small of
1.0 and a value of 1.0, as given by the foregoing rules. The result of
a conversion from a floating point type to a fixed point type shall belong
to the close result set. The result of a conversion of a universal_real
operand to a fixed point type shall belong to the perfect result set.
The possibility of overflow in the result of a predefined
arithmetic operation or conversion yielding a result of a fixed point
type T is analogous to that for floating point types, except for being
related to the base range instead of the safe range.
If
all of the permitted results belong to the base range of T, then the
implementation shall deliver one of the permitted results; otherwise,
if T'Machine_Overflows is
True, the implementation shall either deliver one of the permitted results
or raise Constraint_Error;
if T'Machine_Overflows is False, the result is
implementation defined.
Implementation defined: The result of
a fixed point arithmetic operation in overflow situations, when the Machine_Overflows
attribute of the result type is False.
Inconsistencies With Ada 83
Since the values of a fixed
point type are now just the integer multiples of its
small, the
possibility of using extra bits available in the chosen representation
for extra accuracy rather than for increasing the base range would appear
to be removed, raising the possibility that some fixed point expressions
will yield less accurate results than in Ada 83. However, this is partially
offset by the ability of an implementation to choose a smaller default
small than before. Of course, if it does so for a type T then
T'Small will have a different value than it previously had.
The accuracy requirements in the case of incompatible
smalls are relaxed to foster wider support for nonbinary smalls.
If this relaxation is exploited for a type that was previously supported,
lower accuracy could result; however, there is no particular incentive
to exploit the relaxation in such a case.
Wording Changes from Ada 83
The fixed point
accuracy requirements are now expressed without reference to model or
safe numbers, largely because the full generality of the former model
was never exploited in the case of fixed point types (particularly in
regard to operand perturbation). Although the new formulation in terms
of perfect result sets and close result sets is still verbose, it can
be seen to distill down to two cases:
a case where the result must be the exact
result, if the exact result is representable, or, if not, then either
one of the adjacent values of the type (in some subcases only one of
those adjacent values is allowed);
a case where the accuracy is not specified
by the language.
Wording Changes from Ada 2012
{
AI12-0300-1}
Correction: Reworded the fixed*integer accuracy requirements to
clarify that the only allowed integer type in such operations is Standard.Integer.
We make this correction as readers of the Reference Manual have been
confused on this point.
Ada 2005 and 2012 Editions sponsored in part by Ada-Europe