Defining the value of T'FIRST and T'LAST for real types AI00174/08 1
890616 BI WA
 !standard 03.05 (09) 890616 AI00174/08
!standard 03.05 (08)
!standard 04.05.07 (07)
!standard 04.05.07 (10)
!standard 13.07.03 (04)
!class binding interpretation 840117
 !status WG9approved 890616
!status ARGapproved (reviewed) 881003
!status ARGapproved (1201) 880607 (pending editorial review)
!status ARGapproved (1314) 870915 (pending editorial review)
!status panelapproved (411) 870915 (pending editorial review)
!status panel/committeeapproved (611) 870218 (pending editorial review)
!status workitem 861013
!status received 840117
!references AI00021, AI00469, 8300149, 8300150, 8300904, 8300937,
8300949, 8300947
 !topic Defining the value of T'FIRST and T'LAST for real types
!summary 880823
If T is a real base type, then T'FIRST and T'LAST are, respectively, the
smallest (most negative) and largest finite values that use the
implementation's representation for stored values of type T. The evaluation
of T'FIRST and T'LAST never raises an exception, even if these values lie
outside the range of safe numbers.
If T is a floating point type declared with a range constraint, then T'FIRST
uses the implementation's representation for stored values of type T (i.e.,
T'FIRST is a storable value) and is the result of converting the value of the
lower bound to the type T. In addition, T'FIRST must belong to the range of
T's safe numbers. The same applies to T'LAST and the upper bound of the
range constraint.
If T is a fixed point type declared with a range constraint, then T'FIRST and
T'LAST use the implementation's representation for stored values of type
T. If a bound in T's type declaration is a model number of type T, then the
model number is the value of the corresponding attribute. If a bound falls
in a model interval of type T, the corresponding attribute value is a
specific value in that interval. If the value of a bound lies outside the
range of model numbers (and therefore, lies at most SMALL distant from a
model number), the corresponding attribute value is similarly at most SMALL
distant from the corresponding model number.
If T is a derived real type declared with no range constraint, T'FIRST and T'
LAST are equal to the corresponding values of the parent subtype.
If T is a real subtype declared by a subtype declaration of the form
subtype T is R;
then T'FIRST is the same value as R'FIRST, and T'LAST is the same value as R'
LAST.
Defining the value of T'FIRST and T'LAST for real types AI00174/08 2
890616 BI WA
If T is declared by a subtype declaration with a range constraint, T'FIRST is
the value of the lower bound and T'LAST is the value of the upper bound.
If real type T has a nonnull range, the values of the attributes T'FIRST and
T'LAST belong to the subtype T, i.e., these values are never considered to
lie outside T's range and hence, for example, can always be assigned to an
unconstrained variable of subtype T.
!question 880509
T'LAST yields the upper bound of T. But what is the upper bound of a real
type whose declaration does not have a range constraint? Or a predefined
type such as FLOAT? The problem is that T'LAST need not yield a safe number
(see 3.5.8(19)), and the predefined relational operators <= and < that are
used to define the lower bound and upper bound of a range, and to define the
concept of belonging to a range, are undefined outside the range of safe
numbers (by 4.5.7(7, 10)), because the operand intervals are there undefined.
So if T'LAST is outside the range of safe numbers (in the exact mathematical
sense), then it cannot be distinguished from T'SAFE_LARGE, nor from any
larger machine representable value, and is essentially undefined. Section
4.5.2 does not help much; 4.5.2(4) seems to appeal to 4.5.7 only for the case
of nearly equal values, yet 4.5.7(1) is quite general.
1) What is the definition of T'FIRST and T'LAST for real types?
2) Can T'LAST and T'FIRST always be assigned to an
unconstrained variable of type T without raising CONSTRAINT_
ERROR?
3) Can T'LAST ever raise NUMERIC_ERROR or CONSTRAINT_ERROR,
e.g., for
type F is delta 2.0**(15) range 1.0 .. 1.0;
can F'LAST raise an exception since 1.0 is not a
representable value if F'SIZE = 16?
!recommendation 880509
If T is a real base type, then T'FIRST and T'LAST are, respectively, the
smallest (most negative) and largest finite values that use the
implementation's representation for stored values of type T. The evaluation
of T'FIRST and T'LAST never raises an exception.
If T is a floating point type declared with a range constraint, then T'FIRST
is a storable value of type T (i.e., T'FIRST uses the implementation's
representation for stored values of type T) and is the result of converting
the value of the lower bound to the type T. In addition, T'FIRST must belong
to the range of T's safe numbers. The same applies to T'LAST and the upper
bound of the range constraint.
If T is a fixed point type declared with a range constraint, then T'FIRST and
T'LAST are storable values of type T. If a bound in T's type declaration is a
Defining the value of T'FIRST and T'LAST for real types AI00174/08 3
890616 BI WA
model number of type T, then the model number is the value of the
corresponding attribute. If a bound falls in a model interval of type T, the
corresponding attribute value is a specific value in that interval. If the
value of a bound lies outside the range of model numbers (and therefore, lies
at most SMALL distant from a model number), the corresponding attribute value
is similarly at most SMALL distant from the corresponding model number.
If T is a derived real type declared with no range constraint, T'FIRST and T'
LAST are equal to the corresponding values of the parent subtype.
If T is a real subtype declared by a subtype declaration of the form
subtype T is R;
then T'FIRST is the same value as R'FIRST, and T'LAST is the same value as R'
LAST.
If T is declared by a subtype declaration with a range constraint, T'FIRST is
the value of the lower bound and T'LAST is the value of the upper bound.
If real type T has a nonnull range, the values of the attributes T'FIRST and
T'LAST belong to the subtype T, i.e., these values are never considered to
lie outside T's range and hence, for example, can always be assigned to an
unconstrained variable of subtype T.
!discussion 881003
For a nonnull scalar type, T'FIRST and T'LAST were intended to be,
respectively, the smallest and largest assignable values of the type (i.e.,
the smallest and largest values that can be stored without raising an
exception). Since the recommendation implies that T'LAST belongs to subtype
T, the assignment of T'LAST to an unconstrained variable of type T cannot
raise an exception if T has a nonnull range, e.g.:
X : T := T'LAST;  no exception raised unless T has a null range
X can be assigned the value T'LAST, even when this value is not a safe number
of type T or is outside the range of safe numbers for T's base type.
Although T'LAST can always be assigned to X, not all allowed values of the
EXPRESSION giving the upper bound of a range constraint can necessarily be
assigned. For example, consider the case when the expression defining a
bound of a real type is not a model number, e.g.:
type T is digits 1 range 0.0 .. 0.1;
0.1 is a repeating binary fraction,
2#0.1100_1100_1100_1100_1100_1100_1100_...#E3
Since T'MANTISSA is 5, the model interval containing 0.1 is 2#0.11001#E3 ..
2#0.11010#E3 (which in decimal notation is 0.09765625 .. 0.1015625).
Suppose the machine mantissa has 24 bits, and the value chosen for T'LAST is
the truncated 24bit representation for 0.1:
Defining the value of T'FIRST and T'LAST for real types AI00174/08 4
890616 BI WA
2#0.1100_1100_1100_1100_1100_1100#E3
Now suppose we try to assign a slightly larger value to X, e.g.:
X := 2#0.1100_1100_1100_1100_1100_1101#E3;
Although T'LAST could have been chosen to be as large as 2#0.11010#E3, it
was in fact chosen to be a more accurate representation of 0.1. Hence, the
specified assignment can raise CONSTRAINT_ERROR. Similarly, T'(0.1) could,
in principle, raise CONSTRAINT_ERROR because the literal 0.1 could be
represented as any value in the required model interval. If the chosen value
is greater than the value chosen for T'LAST, CONSTRAINT_ERROR will be raised.
An attempt to assign 0.1 to X could raise CONSTRAINT_ERROR for the same
reason. Nonetheless, an attempt to store T'LAST will always succeed. This
reasoning also applies when T is declared as a subtype:
type S is digits 5;
subtype T is S range 0.0 .. 0.1;
X : T := 0.1;
Y : T := T'LAST;
The assignment to X can raise an exception if the converted value of 0.1 in
this expression exceeds the value of T'LAST, but the assignment to Y can
never raise an exception.
Although T'FIRST and T'LAST always produce representable values, evaluation
of these attributes can produce values that lie outside the range of safe
numbers. Nonetheless, it is intended that such evaluations never raise
NUMERIC_ERROR or CONSTRAINT_ERROR (see AI00021).
11.6(6) permits expressions such as
T'LAST < T'LAST + T'LAST
to be evaluated using a type with a wider range, so NUMERIC_ERROR need not be
raised provided the correct result is produced. This example shows that
values larger than T'LAST can be produced, and hence, it is not acceptable to
say that T'LAST is the largest value of type T, although it is the largest
value that can be stored in a variable of type T.
Implementations are permitted to use some bit patterns of the storage
allocated to a variable of real type T to indicate other than numeric values.
For example, in a twoscomplement machine, the most negative machine value
may be used to indicate an uninitialized object and the next larger machine
value used for T'FIRST. The desired relationships for T'FIRST will still
hold. The bit pattern used to check for uninitialized objects is not
considered to be a storable value of type T.
Implementations must be careful to give T'FIRST and T'LAST a value that is
consistent with the accuracy of STORED values. For example, consider:
type T is delta 2.0**(SYSTEM.MAX_MANTISSA) range 1.0 .. 1.0;
X : T;
Defining the value of T'FIRST and T'LAST for real types AI00174/08 5
890616 BI WA
MAX_MANTISSA is "the largest possible number of binary digits in the mantissa
of model numbers of a fixed point subtype." [13.7.1(5)] If X'SIZE = MAX_
MANTISSA + 1, then just the model numbers can be stored in X. Since T'LAST
must be the largest storable value, T'LAST must be equal to the largest model
number, i.e., T'LAST will be the value that is SMALL less than 1.0.
Another consequence of the recommendation is that implementations must take
care when choosing either T'LAST or the base type for a floating point type
(see AI00469). For example, consider
type T is digits D range L .. U;
where D, L, and U are named numbers. If U, for example, is not a model
number of the selected base type, then after converting U to a representable
value of the base type, the converted value must be a safe number of the base
type. If the converted value lies in an interval whose lower bound is the
largest safe number of the selected base type (see AI00021), then the
converted value can either be this safe number or it can be the upper bound
of the interval. If the safe number is selected, then there is no problem 
T'LAST is T'SAFE_LARGE. However, if the upper bound of the interval is
selected as the converted value and there is some other predefined base type
that includes this value in its range of safe numbers, then this base type
must be selected. If there is no such predefined base type, the declaration
must be rejected. Note that an implementation can avoid rejecting the
initial selection of a base type if it chooses the "right" converted value
for U.
 !appendix 890617

 *****************************************************************************

 !section 03.05 (09) J. Goodenough 890617
 !version 1983
 !topic Replace the summary section with a true summary

 Version /08 of the commentary, although approved by WG 9, would be
 more understandable if the summary really summarized the effect of
 the commentary. It would be better to replace the summary with:

 For a nonnull real type or real subtype T, T'FIRST and T'LAST are
 the smallest and largest storable values of type T or subtype
 T. The evaluation of T'FIRST or T'LAST can never raise any
 exception.