Version 1.1 of acs/ac-00093.txt

Unformatted version of acs/ac-00093.txt version 1.1
Other versions for file acs/ac-00093.txt

!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... :-)

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


Questions? Ask the ACAA Technical Agent