comp.lang.ada
 help / color / mirror / Atom feed
From: "Randy Brukardt" <randy@rrsoftware.com>
Subject: Re: Unconstrained base subtype questions
Date: Thu, 31 Mar 2011 16:24:54 -0500
Date: 2011-03-31T16:24:54-05:00	[thread overview]
Message-ID: <in2rf9$49o$1@munin.nbi.dk> (raw)
In-Reply-To: in2nv8$v3e$1@dont-email.me

"Alex Mentis" <foo@invalid.invalid> wrote in message 
news:in2nv8$v3e$1@dont-email.me...
> The following does not cause a constraint error in my version of GNAT
> on my system:
>
> ...
>
> Integer_Result := (Integer'Last + Integer'Last) / 2;
>
> ...
>
>
> If I understand correctly, this is because the Integer operators are
> defined for operands of type Integer'Base, which is an unconstrained
> subtype and allows the operands to be stored in extended-length
> registers so that intermediate values in calculations do not overflow.

Right. In this case, the compiler is probably just doing constant folding 
using unlimited precision numbers. Does the same thing happen when you use 
variables??

   Last : Integer := Integer'Last;

   Result : Integer :=  (Last + Last)/2;

(Even better, write a function that returns Integer'Last and call it; the 
ACATS uses this technique to reduce optimization of expressions.)

> My questions are:
>
> 1) Do I understand correctly what's going on?

I think so.

> 2) Does the language make any guarantees about preventing spurious
> overflow, or am I just getting lucky with my compiler/architecture? If
> guarantees are made by the language, what are they?

The language says effectively that you either will get the right answer or 
Constraint_Error. But it makes no guarantees about which you will get for 
values outside of the result subtype. So that is compiler-dependent.

The intent is to be able to use the hardware effectively. To take an 
example, older Intel X86 processors did all of their floating point 
calculations in 80-bit registers. The only certain way to use fewer bits was 
to store the register into memory and then reload it (which forced the 
needed rounding). Needless to say, this doesn't help performance!

In something like:
    F := (A * B) / (C * D);
you would have two extra store/load pairs. That's awful, thus the rule 
allowing extra precision.

For float types, Ada actually has an attribute to explicitly discard extra 
precision (S'Machine). For integer types, you'd have to explicitly store the 
subexpression into an object and do a validity test on it. (It's not clear 
to me that a type conversion alone would guarantee a check for a type like 
Integer where Integer has the same range as Integer'Base. The validity rules 
always allow delaying a constraint check, so only 'Valid is certain to smoke 
out overflowing values.)

But both of these operations are expensive, and should only be used when 
absolute portability is needed.

                                  Randy.





  parent reply	other threads:[~2011-03-31 21:24 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-03-31 20:25 Unconstrained base subtype questions Alex Mentis
2011-03-31 21:09 ` Ludovic Brenta
2011-03-31 21:26   ` Alex Mentis
2011-03-31 21:36     ` Ludovic Brenta
2011-03-31 22:18       ` Adam Beneschan
2011-03-31 21:10 ` Adam Beneschan
2011-03-31 21:18 ` Simon Wright
2011-03-31 21:24 ` Randy Brukardt [this message]
2011-03-31 21:51   ` Alex Mentis
2011-04-01  8:20     ` Dmitry A. Kazakov
replies disabled

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox