======= 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