!standard 3.05(11) 04-02-05 AC95-00093/01 !class amendment 04-02-05 !status received no action 04-02-05 !status received 04-01-23 !subject Limit attribute !summary A new attribute of scalar types is introduced to allow results of arithmetic operations to be limited to a known range. !problem A common technique of avoiding exceptions within embedded systems is to check against known 'safe' ranges and limit results to within this range. Generics can be created that can do this but requires the user to add instances for each type - often there can be dozens, occasionally hundreds, of such instantiations. This functionality would be trivial for the language to provide in much the same way as S'Min and S'Max currently are. !proposal Add an attribute function, S'Limit(Val), which is defined for scalar types. Its parameter is of type S'Base. The result is a value of type S, whose value is always within the range of type S, such that the result is S'First if Val < S'First, S'Last if Val is > S'Last, or Val if S'First <= Val <= S'Last. !wording Include in 3.5(11): S'Limit S'Limit denotes a function with the following specification: function S'Limit (Arg : S'Base) return S This function returns a value within the range of type S, such that if Arg < S'First then S'First is returned, if Arg > S'Last then S'Last is return, otherwise Arg is returned. !example type Integer_32 is range -(2**31) .. 2**31 - 1; subtype Safe_Integer is Integer range 0 .. 100; A : Safe_Integer := Safe_Integer'Last; B : Safe_Integer; begin B := Safe_Integer'Limit (A + 10); -- B is assign the value 100 ... !discussion Here is an example of a generic that can currently be used that provides the required functionality for fixed-point types: generic type T is delta <>; function Generic_Limit_Fixed (V : T'Base) return T; function Generic_Limit_Fixed (V : T'Base) return T is begin if V < T'First then return T'First; elsif V > T'Last then return T'Last; else return V; end if; end Generic_Limit_Fixed; Such a unit is required for integer, floating point, decimal, etc. !ACATS test Add an ACATS test checking the presence and operation of the Limit attribute. !appendix From: Adam Beneschan Sent: Friday, January 23, 2004 1:24 PM > Add an attribute function, S'Limit(Val), which is defined for scalar > types. Its parameter is of type S'Base. The result is a value of > type S, whose value is always within the range of type S, such that > the result is S'First if Val < S'First, S'Last if Val is > S'Last, > or Val if S'First <= Val <= S'Last. Some processors have instructions that perform similar functions. Texas Instruments' TMS320C62x/C67x/C64x, e.g., has "saturation" instructions such as SADD. For 32-bit integers, this effect of this instruction is to add two integers A and B, and return 2**32-1 if A+B >= 2**32, -2**32 if A+B < 2**32, and A+B otherwise. My immediate first thought was that Martin's proposal would be useful for allowing compilers to take advantage of instructions like that. However, it won't really work, because the argument of S'Limit has to be within the base range of the type in the first place. If your type is a 32-bit integer type, you'd have to convert the arguments of the addition to a larger type, define S to be a 32-bit subtype of that larger type, convert the result back ... which not only seems clunky but can't be done if there is no larger type in the first place. I'm not sure whether this is something that ought to be addressed. I just happen to know that the "saturate" instructions exist, but I've never had a need to use anything like that. **************************************************************** From: Tucker Taft Sent: Friday, January 23, 2004 9:08 PM I was involved with the design of a language which had a feature like this, but as Adam points out, Martin's proposal doesn't really solve the problem. What you want is "saturating" arithmetic, not "saturating" range check. It is easy to implement a "saturating" range check yourself. It is not pleasant to have to implement saturating arithmetic yourself, and it is particularly unpleasant if the hardware knows how to do it itself. This language we were designing had something S'Limit() but it took an *expression* as an operand, and required that the entire expression be evaluated using saturating arithmetic, rather than overflow-signaling arithmetic. Personally, I think a more natural solution in Ada would be to have a representation clause/pragma associated with the type, analagous to "'Machine_Overflows", which would be something like "'Machine_Saturates". Ideally it would be a specifiable attribute, so you could have some types that saturate, and others that overflow, and you would use one or the other as appropriate to a particular calculation. **************************************************************** From: Martin Dowie Sent: Saturday, January 24, 2004 2:08 AM The benefit of an attribute to do this is that there is no 'surprise' at the point of use for a reader. My first thought had been something like: type Foo is limited range 1 .. 100; **************************************************************** From: Martin Dowie Sent: Saturday, January 24, 2004 2:52 AM > My immediate first thought was that Martin's proposal would be useful > for allowing compilers to take advantage of instructions like that. > However, it won't really work, because the argument of S'Limit has to > be within the base range of the type in the first place. Hmmm, instead of defining on version for all scalars, would overloaded versions that took universal_integer/real/fixed (not bothered about enumerations really) be workable? **************************************************************** From: Jean-Pierre Rosen Sent: Saturday, January 24, 2004 10:26 AM > Personally, I think a more natural solution in Ada > would be to have a representation clause/pragma associated > with the type, analagous to "'Machine_Overflows", which > would be something like "'Machine_Saturates". Ideally > it would be a specifiable attribute, so you could have > some types that saturate, and others that overflow, > and you would use one or the other as appropriate to > a particular calculation. > Or rather, do what we did when we introduced modular types. Introduce a new kind of integer types: type Int is range limited 1..255; **************************************************************** From: Martin Dowie Sent: Monday, January 26, 2004 7:38 AM > The benefit of an attribute to do this is that there is no 'surprise' > at the point of use for a reader. Having said that, the unsuspecting reader may already be 'surprised' by Modular types... :-) ****************************************************************