======= LSN011.Numerics =======
!topic LSN on Ada 9X Real Accuracy Model
!reference MD-3.5.6(2);2.0
!reference MD-G.5;2.0
!from Tucker Taft 91-06-06
!discussion
We have never been very specific about our proposals regarding
the 9X accuracy model for real types. This LSN is a first cut at formalizing
our proposal and some of the considerations behind it.
Our overall goal is to slim down discussion of real accuracy
in the core of the RM, move what we still need to a Numerics Annex,
and generally tie the accuracy model more to the machine characteristics
than to an arbitrary model. We also intend to provide
more, hopefully useful, attributes and attribute functions to
support numerically oriented Ada programmers.
Finally, we want to incorporate the NRG's Generic Elementary
Functions into the 9X standard.
ELIMINATE REDUCED ACCURACY SUBTYPES
In accordance with the relatively recent AI-571 (which reversed AI-407),
reduced accuracy subtypes of a real type must retain the full
accuracy of the safe numbers, even on assignment.
This implies that reduced accuracy subtypes, i.e. those with a
smaller number of DIGITS or a larger DELTA, are of little value
(other than perhaps documentation).
Given the above, we have proposed (with little opposition) to remove
reduced accuracy subtypes from the language.
The major advantage of this removal is a dramatic
simplification in the accuracy model of real types, allowing
us to talk only in terms of "safe" numbers, and eliminate all discussion
of subtype-specific model numbers.
The attributes of safe numbers are always static, whereas the attributes
of model numbers in certain unusual cases are dynamic, requiring
some amount of run-time support (and all the compiler complexity
of generating a call on this run-time support at the appropriate place
with the appropriate parameters).
One syntactic effect of eliminating accuracy subtype constraints
is that the DELTA and DIGITS specifications are now only legal
as part of a real type declaration (rather than as part of a
subtype indication).
Furthermore, this allows us to distinguish the range specifications
used in numeric type declarations from those used in numeric
range constraints, which is nice since
they have quite different semantic rules.
In particular, in type declarations, the bounds of the range
can be any real (any integer) type for a real (integer) type declaration.
In a range constraint, the bounds of the range must be of the
type being constrained.
Eliminating accuracy subtype constraints also cuts down on the total distinct
kinds of constraints from 5 to 3, simplifying the description of other
language features which use constraints, such as the membership operation.
EXISTING REAL ATTRIBUTES
Given our dropping of the notion of model numbers for subtypes,
and our desire to make safe numbers more nearly reflect the
machine numbers, there remains the question of how the existing
attributes should be redefined for 9X.
First of all, we propose that MANTISSA be changed to be as large
as possible consistent with the accuracy of the underlying chosen
representation. For decent binary-radix hardware, MANTISSA and
MACHINE_MANTISSA will be the same.
For hexadecimal-radix hardware, MANTISSA would remain a count
of binary digits, given that existing programs may assume
that 2**MANTISSA is a meaningful thing.
In other words, we are retaining the binary-radix-oriented model
for safe numbers. Although we might prefer going to a full
machine-radix-oriented model, it seems like it may introduce
too many upward incompatibilities. Given that the machine attributes
are also available, it does not seem essential that safe numbers
be based on the machine radix.
This change to MANTISSA carries over to the definition
of EPSILON (see RM 3.5.8(17)) giving T'EPSILON = 2.0**(1-T'MANTISSA).
However, in 9X, we propose that the MANTISSA does not
determine EMAX or SMALL. Instead we propose to make EMAX, SMALL, and LARGE
synonymous with SAFE_EMAX, SAFE_SMALL, and SAFE_LARGE,
reflecting as close as possible the (binary-model) properties
of the chosen representation.
The above changes are not strictly upward-compatible, but
it seems very unlikely that existing programs depended on
the "pessimism" of the Ada-83 attribute values. However, as mentioned
above, we are proposing to retain the binary-ness of the safe
number model.
SUMMARY OF 9X SAFE NUMBER MODEL
The 9X safe numbers correspond to a set of binary-radix floating
point numbers which can be represented exactly by the underlying
hardware, and which satisfy the interval-based accuracy model requirements.
The safe numbers do *not* include denormalized numbers or
extended-precision numbers.
ADDITIONAL ATTRIBUTES
There is a Study Topic which implies providing
additional floating-point attributes/attribute-functions
which can improve the predictability of floating point operations.
Brian Wichmann, in conjunction with Robert and others, has made
a fairly complete proposal in this area, based on the LCAS
(Language Compatible Arithmetic Standard) model
which Brian has proposed. It seems reasonable to add
the necessary MACHINE_* attributes to support this approach,
at least in a "Numerics annex."
In talking with other members of the Numerics Rapporteur Group, however,
there was some concern that the predictability promised by LCAS
would not always be useful, because of the problem of extended
intermediate values. In particular, due to optimizations, or
normal register allocation, certain computations may be performed,
and certain intermediate values may be retained, in an extended
precision representation. Furthermore, the transitions from
normal precision to extended precision happen at unpredictable
times, due to the vagueries of the optimization algorithm,
or worse, to the vagueries of interrupts where only non-extended
precision data is saved and restored (we have been assured
that this only happens in very unfriendly O/Ss).
Therefore, given the possibility of extended-precision
intermediates, it is not always possible (or practical) to
predict how many distinct rounding steps will occur as part
of performing a calculation, resulting in the kinds of "nondeterminism"
inherent in the Brown interval-based model.
Therefore, even given LCAS-style attributes, it may also be
useful to provide an attribute function which can force
extended precision or denormalized values to be eliminated.
We are therefore proposing that the following
attribute function be provided:
T'SAFE(value)
This attribute function returns a safe number of the type T,
given a value of the type T. The safe number is the "natural"
one associated with the value, using the normal rounding/truncating
behavior of the hardware. In other words, T'SAFE(value) forces
the value to a neighboring safe number, shedding excess precision
or denormalized values.
IEEE FLOATING POINT ISSUES
An additional set of issues is related to the IEEE floating point standard.
This standard requires that certain capabilities be made available,
although it is pretty flexible as to how the capabilities are mapped
to specific language or run-time features.
Perhaps the main problems related to Ada have to do with "negative zero,"
other "special" numbers like NaN, and plus and minus infinity,
and dynamic user control over rounding and overflow behavior.
If we have dynamic user control over rounding and overflow, then some of
the MACHINE_* attributes may want to be dynamic rather than static.
However, this causes problems if there is any requirement
that any conversions from infinitely-precise universal real
literals be performed at compile-time consistent with the
current settings of the attributes.
Therefore, we would propose the following alternative:
A pragma, rep-clause, or compiler mode be used to
specify the value for these variable attributes.
It is the programmer's responsibility to ensure
that the appropriate control operations have been performed
on the floating point hardware (perhaps via a standard IEEE
binding), so that the statically-specified attribute values
correspond to the values in effect at run-time for the corresponding
part of the program.
The rationale for this is that it is relatively expensive to change
the rounding/overflow behavior, and one certainly doesn't want to
do it every time a subprogram is entered unless necessary.
However, when coupled with a desire to allow different parts of
the program to operate with different rounding/overflow behavior,
and a desire to know at compile-time what rounding/overflow behavior
is in effect in any given part, only the programmer can decide
where and when to insert calls on the actual hardware control operations.
Note that this is a case where the rounding/overflow behavior is
not associated with the type (even though the attribute is),
but rather with the state of the hardware at the time a particular
operation is performed.
Therefore, to summarize:
If certain MACHINE_* attributes are to be changable, but the
compiler needs to know their value statically, then the compiler
should be informed statically of the setting, and the programmer
should take responsibility for performing a dynamic call at run-time
to get the right setting in force.
Note that if there are IEEE-specific settings which are of no interest
to the compiler, then they are probably best handled through normal
subprograms in an IEEE binding package. Such settings could be
totally dynamic, changed at will with their value determined completely
dynamically.
As far as NaN, and plus and minus infinity, it seems important to
at least "allow" a mode where these values are produced rather
than CONSTRAINT_ERRORs.
Negative zero seems to only come up in some subtle cases having
to do with ArcTan, and the Generic Elementary Functions seem
to have already dealt with that as best as is possible.
Speaking of which...
GENERIC ELEMENTARY FUNCTIONS PACKAGE
We intend to include the Generic Elementary Functions (GEF)
pretty much as-is in the Numerics Annex. With the ability to use
T'BASE as a legitimate subtype in 9X, we may be able to relax
the restriction on instantiation with range-constrained subtypes.
The NRG seems comfortable with this standard being totally subsumed within
the Ada standard, so that an independent ISO standard need no longer
be maintained. One DR concern is how large this would make the Numerics
Annex.
GENERIC PRIMITIVE FUNCTIONS PACKAGE
Our current proposal is to eliminate the need for the Generic
Primitive Functions (GPF) package, by providing sufficient attributes
and attribute functions in the Numerics Annex.
We have yet to decide on names for these attributes and attribute
functions, but they would insofar as possible be the same as
those in the GPF package.
Our view is that providing things like Exponent and Fraction
via a specially-recognized generic is actually harder for
implementors than providing them via builtin attributes.
Note, however, that once the attributes exist it is trivial
to implement a generic package like GPF, in pure Ada,
so we can preserve upward compatibility this way.
-Tuck