A.5.3 Attributes of Floating Point Types
Static Semantics
The
following
representation-oriented attributes are defined for every
subtype S of a floating point type
T.
S'Machine_Radix
Yields the radix of the hardware
representation of the type
T. The value of this attribute is of
the type
universal_integer.
The values of other representation-oriented
attributes of a floating point subtype, and of the “primitive function”
attributes of a floating point subtype described later, are defined in
terms of a particular representation of nonzero values called the
canonical
form. The canonical form (for the type
T) is the form
±
mantissa
·
T'Machine_Radixexponent
where
mantissa is a fraction in the number base
T'Machine_Radix, the first digit of which is nonzero, and
exponent is an integer.
S'Machine_Mantissa
Yields the largest value of
p
such that every value expressible in the canonical form (for the type
T), having a
p-digit
mantissa
and an
exponent between
T'Machine_Emin and
T'Machine_Emax,
is a machine number (see
3.5.7) of the type
T. This attribute yields a value of the type
universal_integer.
Ramification: Values of a type held in
an extended register are, in general, not machine numbers of the type,
since they cannot be expressed in the canonical form with a sufficiently
short mantissa.
S'Machine_Emin
Yields the smallest (most negative)
value of
exponent such that every value expressible in the canonical
form (for the type
T), having a
mantissa of
T'Machine_Mantissa
digits, is a machine number (see
3.5.7) of
the type
T. This attribute yields a value of the type
universal_integer.
S'Machine_Emax
Yields the largest (most positive)
value of
exponent such that every value expressible in the canonical
form (for the type
T), having a
mantissa of
T'Machine_Mantissa
digits, is a machine number (see
3.5.7) of
the type
T. This attribute yields a value of the type
universal_integer.
Ramification: Note that the above definitions
do not determine unique values for the representation-oriented attributes
of floating point types. The implementation may choose any set of values
that collectively satisfies the definitions.
S'Denorm
Yields the value True if every
value expressible in the form
±
mantissa
·
T'Machine_RadixT'Machine_Emin
where
mantissa is a nonzero
T'Machine_Mantissa-digit fraction
in the number base
T'Machine_Radix, the first digit of which is
zero, is a machine number (see
3.5.7) of
the type
T; yields the value False otherwise. The value of this
attribute is of the predefined type Boolean.
The values described by the formula
in the definition of S'Denorm are called
denormalized numbers.
A nonzero machine number that is not a denormalized
number is a
normalized number.
A
normalized number
x of a given type
T is said to be
represented in canonical form when it is
expressed in the canonical form (for the type
T) with a
mantissa
having
T'Machine_Mantissa digits; the resulting form is the
canonical-form
representation of
x.
Discussion: The intent is that S'Denorm
be True when such denormalized numbers exist and are generated in the
circumstances defined by IEC 559:1989, though the latter requirement
is not formalized here.
S'Machine_Rounds
Yields the value True if rounding
is performed on inexact results of every predefined operation that yields
a result of the type
T; yields the value False otherwise. The
value of this attribute is of the predefined type Boolean.
Discussion:
It is difficult to be more precise about what it means to round the
result of a predefined operation. If the implementation does not use
extended registers, so that every arithmetic result is necessarily a
machine number, then rounding seems to imply two things:
S'Model_Mantissa = S'Machine_Mantissa, so
that operand preperturbation never occurs;
when the exact mathematical result is not
a machine number, the result of a predefined operation must be the nearer
of the two adjacent machine numbers.
Technically, this attribute should yield False
when extended registers are used, since a few computed results will cross
over the half-way point as a result of double rounding, if and when a
value held in an extended register has to be reduced in precision to
that of the machine numbers. It does not seem desirable to preclude the
use of extended registers when S'Machine_Rounds could otherwise be True.
S'Machine_Overflows
Yields the value True if overflow
and divide-by-zero are detected and reported by raising Constraint_Error
for every predefined operation that yields a result of the type
T;
yields the value False otherwise. The value of this attribute is of the
predefined type Boolean.
S'Signed_Zeros
Yields the value True if the
hardware representation for the type
T has the capability of representing
both positively and negatively signed zeros, these being generated and
used by the predefined operations of the type
T as specified in
IEC 559:1989; yields the value False otherwise. The value of this attribute
is of the predefined type Boolean.
For
every value
x of a floating point type
T, the
normalized exponent of
x
is defined as follows:
the normalized exponent of zero is (by convention)
zero;
for nonzero x,
the normalized exponent of x is the
unique integer k such that T'Machine_Radixk–1
≤ |x| < T'Machine_Radixk.
Ramification: The normalized exponent
of a normalized number x is the value
of exponent in the canonical-form representation of x.
The normalized exponent of a denormalized number
is less than the value of T'Machine_Emin.
The
following
primitive function attributes are defined for any subtype
S of a floating point type
T.
S'Exponent
S'Exponent denotes a function
with the following specification:
function S'Exponent (X : T)
return universal_integer
The function yields the normalized exponent
of X.
S'Fraction
S'Fraction denotes a function
with the following specification:
function S'Fraction (X : T)
return T
The function yields the value X
· T'Machine_Radix–k,
where k is the normalized exponent
of X. A zero result[, which can only occur when X is zero,]
has the sign of X.
Discussion: Informally, when X
is a normalized number, the result is the value obtained by replacing
the exponent by zero in the canonical-form representation of X.
Ramification: Except when X is
zero, the magnitude of the result is greater than or equal to the reciprocal
of T'Machine_Radix and less than one; consequently, the result
is always a normalized number, even when X is a denormalized number.
Implementation Note: When X is
a denormalized number, the result is the value obtained by replacing
the exponent by zero in the canonical-form representation of the
result of scaling X up sufficiently to normalize it.
S'Compose
S'Compose denotes a function
with the following specification:
function S'Compose (Fraction : T;
Exponent : universal_integer)
return T
Let
v
be the value
Fraction ·
T'Machine_RadixExponent–k,
where
k is the normalized exponent
of
Fraction. If
v is a machine
number of the type
T, or if |
v|
≥
T'Model_Small,
the function yields
v; otherwise, it
yields either one of the machine numbers of the type
T adjacent
to
v.
Constraint_Error
is optionally raised if
v is outside
the base range of S. A zero result has the sign of
Fraction when
S'Signed_Zeros is True.
Discussion: Informally, when Fraction
and v are both normalized numbers,
the result is the value obtained by replacing the exponent by
Exponent in the canonical-form representation of Fraction.
Ramification: If Exponent is less
than T'Machine_Emin and Fraction is nonzero, the result
is either zero, T'Model_Small, or (if T'Denorm is True)
a denormalized number.
S'Scaling
S'Scaling denotes a function
with the following specification:
function S'Scaling (X : T;
Adjustment : universal_integer)
return T
Let
v
be the value
X ·
T'Machine_RadixAdjustment.
If
v is a machine number of the type
T, or if |
v| ≥
T'Model_Small,
the function yields
v; otherwise, it
yields either one of the machine numbers of the type
T adjacent
to
v.
Constraint_Error
is optionally raised if
v is outside
the base range of S. A zero result has the sign of
X when S'Signed_Zeros
is True.
Discussion: Informally, when X
and v are both normalized numbers,
the result is the value obtained by increasing the exponent by
Adjustment in the canonical-form representation of X.
Ramification: If Adjustment is
sufficiently small (i.e., sufficiently negative), the result is either
zero, T'Model_Small, or (if T'Denorm is True) a denormalized
number.
S'Floor
S'Floor denotes a function with
the following specification:
function S'Floor (X : T)
return T
The function yields the value Floor(X),
i.e., the largest (most positive) integral value less than or equal to
X. When X is zero, the result has the sign of X;
a zero result otherwise has a positive sign.
S'Ceiling
S'Ceiling denotes a function
with the following specification:
function S'Ceiling (X : T)
return T
The function yields the value Ceiling(X),
i.e., the smallest (most negative) integral value greater than or equal
to X. When X is zero, the result has the sign of X;
a zero result otherwise has a negative sign when S'Signed_Zeros is True.
S'Rounding
S'Rounding denotes a function
with the following specification:
function S'Rounding (X : T)
return T
The function yields the integral value
nearest to X, rounding away from zero if X lies exactly
halfway between two integers. A zero result has the sign of X
when S'Signed_Zeros is True.
S'Unbiased_Rounding
S'Unbiased_Rounding denotes a
function with the following specification:
function S'Unbiased_Rounding (X : T)
return T
The function yields the integral value
nearest to X, rounding toward the even integer if X lies
exactly halfway between two integers. A zero result has the sign of X
when S'Signed_Zeros is True.
S'Machine_Rounding
{
AI95-00267-01}
S'Machine_Rounding denotes a function with the following specification:
function S'Machine_Rounding (X : T)
return T
The function yields the integral value
nearest to
X. If
X lies exactly halfway between two integers,
one of those integers is returned, but which of them is returned is unspecified.
A zero result has the sign of
X when S'Signed_Zeros is True. This
function provides access to the rounding behavior which is most efficient
on the target processor.
Discussion: We leave the rounding unspecified,
so that users cannot depend on a particular rounding. This attribute
is intended for use in cases where the particular rounding chosen is
irrelevant. If there is a need to know which way values halfway between
two integers are rounded, one of the other rounding attributes should
be used.
S'Truncation
S'Truncation denotes a function
with the following specification:
function S'Truncation (X : T)
return T
The function yields the value Ceiling(X)
when X is negative, and Floor(X)
otherwise. A zero result has the sign of X when S'Signed_Zeros
is True.
S'Remainder
S'Remainder denotes a function
with the following specification:
function S'Remainder (X, Y : T)
return T
For nonzero
Y,
let
v be the value
X
–
n ·
Y,
where
n is the integer nearest to the
exact value of
X/
Y;
if |
n –
X/
Y|
= 1/2, then
n is chosen to be even.
If
v is a machine number of the type
T, the function yields
v; otherwise,
it yields zero.
Constraint_Error
is raised if
Y is zero. A zero result has the sign of
X
when S'Signed_Zeros is True.
Ramification: The magnitude of the result
is less than or equal to one-half the magnitude of Y.
Discussion: Given machine numbers X
and Y of the type T, v
is necessarily a machine number of the type T, except when Y
is in the neighborhood of zero, X is sufficiently close to a multiple
of Y, and T'Denorm is False.
S'Adjacent
S'Adjacent denotes a function
with the following specification:
function S'Adjacent (X, Towards : T)
return T
If
Towards
=
X, the function yields
X;
otherwise, it yields the machine number of the type
T adjacent
to
X in the direction of
Towards, if that machine number
exists.
If the result would be
outside the base range of S, Constraint_Error is raised. When
T'Signed_Zeros
is True, a zero result has the sign of
X. When
Towards
is zero, its sign has no bearing on the result.
Ramification: The value of S'Adjacent(0.0,
1.0) is the smallest normalized positive number of the type T
when T'Denorm is False and the smallest denormalized positive
number of the type T when T'Denorm is True.
S'Copy_Sign
S'Copy_Sign denotes a function
with the following specification:
function S'Copy_Sign (Value, Sign : T)
return T
If the value of
Value
is nonzero, the function yields a result whose magnitude is that of
Value
and whose sign is that of
Sign; otherwise, it yields the value
zero.
Constraint_Error is optionally
raised if the result is outside the base range of S. A zero result has
the sign of
Sign when S'Signed_Zeros is True.
Discussion: S'Copy_Sign is provided for
convenience in restoring the sign to a quantity from which it has been
temporarily removed, or to a related quantity. When S'Signed_Zeros is
True, it is also instrumental in determining the sign of a zero quantity,
when required. (Because negative and positive zeros compare equal in
systems conforming to IEC 559:1989, a negative zero does not appear
to be negative when compared to zero.) The sign determination is accomplished
by transferring the sign of the zero quantity to a nonzero quantity and
then testing for a negative result.
S'Leading_Part
S'Leading_Part denotes a function
with the following specification:
function S'Leading_Part (X : T;
Radix_Digits : universal_integer)
return T
Let v
be the value T'Machine_Radixk–Radix_Digits,
where k is the normalized exponent
of X. The function yields the value
Floor(X/v)
· v, when X is nonnegative
and Radix_Digits is positive;
Ceiling(X/v)
· v, when X is negative
and Radix_Digits is positive.
Constraint_Error
is raised when
Radix_Digits is zero or negative. A zero result[,
which can only occur when
X is zero,] has the sign of
X.
Discussion: Informally, if X is
nonzero, the result is the value obtained by retaining only the specified
number of (leading) significant digits of X (in the machine radix),
setting all other digits to zero.
Implementation Note: The result can be
obtained by first scaling X up, if necessary to normalize it,
then masking the mantissa so as to retain only the specified number of
leading digits, then scaling the result back down if X was scaled
up.
S'Machine
S'Machine denotes a function
with the following specification:
function S'Machine (X : T)
return T
If
X is a machine
number of the type
T, the function yields
X; otherwise,
it yields the value obtained by rounding or truncating
X to either
one of the adjacent machine numbers of the type
T.
Constraint_Error
is raised if rounding or truncating
X to the precision of the
machine numbers results in a value outside the base range of S. A zero
result has the sign of
X when S'Signed_Zeros is True.
Discussion: {
AI05-0005-1}
All of the primitive function attributes except Rounding and Machine
correspond to subprograms in the Generic_Primitive_Functions generic
package that was proposed as a separate ISO standard (ISO/IEC DIS 11729)
for Ada 83. The Scaling, Unbiased_Rounding, and Truncation attributes
correspond to the Scale, Round, and Truncate functions, respectively,
in Generic_Primitive_Functions. The Rounding attribute rounds away from
zero; this functionality was not provided in Generic_Primitive_Functions.
The name Round was not available for either of the primitive function
attributes that perform rounding, since an attribute of that name is
used for a different purpose for decimal fixed point types. Likewise,
the name Scale was not available, since an attribute of that name is
also used for a different purpose for decimal fixed point types. The
functionality of the Machine attribute was also not provided in Generic_Primitive_Functions.
The functionality of the Decompose procedure of Generic_Primitive_Functions
is only provided in the form of the separate attributes Exponent and
Fraction. The functionality of the Successor and Predecessor functions
of Generic_Primitive_Functions is provided by the extension of the existing
Succ and Pred attributes.
Implementation Note: The primitive function
attributes may be implemented either with appropriate floating point
arithmetic operations or with integer and logical operations that act
on parts of the representation directly. The latter is strongly encouraged
when it is more efficient than the former; it is mandatory when the former
cannot deliver the required accuracy due to limitations of the implementation's
arithmetic operations.
The
following
model-oriented attributes are defined for any subtype
S of a floating point type
T.
S'Model_Mantissa
If the Numerics Annex is not
supported, this attribute yields an implementation defined value that
is greater than or equal to
Ceiling(
d
· log(10) / log(
T'
Machine_Radix))
+ 1, where
d is the requested decimal
precision of
T, and less than or equal to the value of
T'Machine_Mantissa.
See
G.2.2 for further requirements that apply
to implementations supporting the Numerics Annex. The value of this attribute
is of the type
universal_integer.
S'Model_Emin
If the Numerics Annex is not
supported, this attribute yields an implementation defined value that
is greater than or equal to the value of
T'Machine_Emin. See
G.2.2
for further requirements that apply to implementations supporting the
Numerics Annex. The value of this attribute is of the type
universal_integer.
S'Model_Epsilon
Yields the value
T'Machine_Radix1
– T'Model_Mantissa.
The value of this attribute is of the type
universal_real.
Discussion: In most implementations,
this attribute yields the absolute value of the difference between one
and the smallest machine number of the type
T above one which,
when added to one, yields a machine number different from one. Further
discussion can be found in
G.2.2.
S'Model_Small
Yields the value
T'Machine_RadixT'Model_Emin – 1. The value of this attribute is of the
type
universal_real.
Discussion: In most implementations,
this attribute yields the smallest positive normalized number of the
type
T, i.e. the number corresponding to the positive underflow
threshold. In some implementations employing a radix-complement representation
for the type
T, the positive underflow threshold is closer to
zero than is the negative underflow threshold, with the consequence that
the smallest positive normalized number does not coincide with the positive
underflow threshold (i.e., it exceeds the latter). Further discussion
can be found in
G.2.2.
S'Model
S'Model denotes a function with
the following specification:
function S'Model (X : T)
return T
If the Numerics Annex is not supported,
the meaning of this attribute is implementation defined; see
G.2.2
for the definition that applies to implementations supporting the Numerics
Annex.
S'Safe_First
Yields the lower bound of the
safe range (see
3.5.7) of the type
T.
If the Numerics Annex is not supported, the value of this attribute is
implementation defined; see
G.2.2 for the
definition that applies to implementations supporting the Numerics Annex.
The value of this attribute is of the type
universal_real.
S'Safe_Last
Yields the upper bound of the
safe range (see
3.5.7) of the type
T.
If the Numerics Annex is not supported, the value of this attribute is
implementation defined; see
G.2.2 for the
definition that applies to implementations supporting the Numerics Annex.
The value of this attribute is of the type
universal_real.
Discussion: A predefined floating point
arithmetic operation that yields a value in the safe range of its result
type is guaranteed not to overflow.
To be honest: An exception is made for
exponentiation by a negative exponent in
4.5.6.
Implementation defined: The values of
the Model_Mantissa, Model_Emin, Model_Epsilon, Model, Safe_First, and
Safe_Last attributes, if the Numerics Annex is not supported.
Incompatibilities With Ada 83
The Epsilon and Mantissa
attributes of floating point types are removed from the language and
replaced by Model_Epsilon and Model_Mantissa, which may have different
values (as a result of changes in the definition of model numbers); the
replacement of one set of attributes by another is intended to convert
what would be an inconsistent change into an incompatible change.
The Emax, Small, Large, Safe_Emax, Safe_Small,
and Safe_Large attributes of floating point types are removed from the
language. Small and Safe_Small are collectively replaced by Model_Small,
which is functionally equivalent to Safe_Small, though it may have a
slightly different value. The others are collectively replaced by Safe_First
and Safe_Last. Safe_Last is functionally equivalent to Safe_Large, though
it may have a different value; Safe_First is comparable to the negation
of Safe_Large but may differ slightly from it as well as from the negation
of Safe_Last. Emax and Safe_Emax had relatively few uses in Ada 83; T'Safe_Emax
can be computed in the revised language as Integer'Min(T'Exponent(T'Safe_First),
T'Exponent(T'Safe_Last)).
Implementations are encouraged to eliminate
the incompatibilities discussed here by retaining the old attributes,
during a transition period, in the form of implementation-defined attributes
with their former values.
Extensions to Ada 83
The Model_Emin attribute
is new. It is conceptually similar to the negation of Safe_Emax attribute
of Ada 83, adjusted for the fact that the model numbers now have the
hardware radix. It is a fundamental determinant, along with Model_Mantissa,
of the set of model numbers of a type (see
G.2.1).
The Denorm and Signed_Zeros attributes are new,
as are all of the primitive function attributes.
Extensions to Ada 95
Ada 2005 and 2012 Editions sponsored in part by Ada-Europe