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.
next prev 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