comp.lang.ada
 help / color / mirror / Atom feed
* Constraint_Error in arithmetic expressions
@ 2003-01-12 12:36 Michal Nowak
  2003-01-12 23:37 ` Robert A Duff
  0 siblings, 1 reply; 4+ messages in thread
From: Michal Nowak @ 2003-01-12 12:36 UTC (permalink / raw)


Hello,

I've been reading chapter about exceptions in Cohen's
"Ada as a Second Language". In section 14.3.1 Constraint_Error
there are points concerning raising exception in arithmetic
expressions:

"In the evaluation of an arithmetic expression, an intermediate
result that overflows may raise Constraint_Error, but it is not
guaranteed to do so. There are several reasons for this:
...

o  As explained in Section 4.6, a type declared as
      type T is range A .. B;
   really declares T to be a subtype of some anonymous type whose
   range includes the range A .. B. For Constraint_Error to be raised,
   it is not enough for the subtype range A .. B to be exceeded; the
   wider base-subtype range T'Base'First .. T'Base'Last must be
   exceeded. Whether this happens depends on the anonymous type that
   the compiler selects for T."

Suppose that if I declare:
   type T is range 1 .. 200;
   A : T := 150;
   B : T := 150;
the compiler may choose 1 byte (0 .. 255) or 2 bytes (0 .. 65535) for
example, for the base subtype.
If I do:
(A + B)/2 
I will get Constraint_Error if the compiler has chosen the range (0 .. 255)
for the base type (because 150 + 150 > 255) or I will not if it has chosen
the range (0 .. 65535).

For the rest of the post assume that the compiler chooses the base type
to be in range (0 .. 255), so if I do:
A : T := 100;
B : T := 105;
C : T := (A + B)/2;
I may (or may not) get an exception, but if do:
A : T := 150;
B : T := 150;
C : T := (A + B)/2;
I will get an exception. Am I right?

However, in "ASL" there is another paragraph just after the one mentioned
above:
o  Some compilers may avoid Constraint_Error by using a type with even
   a larger range than the _base subtype_ to evaluate arithmetic
expressions.
   For example, a compiler that represents values of type Integer in a word
   of memory may use two words to hold the result of a multiplication.
   This might avoid overflow in an expressions like A*B/C.

I must say that it made me a bit confused. From the first quoted paragraph
I concluded that if T'Base'First or T'Base'Last will be excluded I will
get an exception. Reading the second made me think that it does not have
to be true, so it contradicts the first one. I suppose that I'm missing 
something, but I don't know what.
I appreciate any explanations,
   Michal


-- -----------------------------------------------------------------
--   ___        _
--  / _ \      | |                      I Choose Ada:
-- | |_| |  ___| |   _____   The Most Trusted Name in Software (TM)
-- |  _  | | __  |  | __  | 
-- |_| |_| |_____|_ |_____|_ http://www.adaic.org/whyada/choose.html
--
-- -----------------------------------------------------------------




^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: Constraint_Error in arithmetic expressions
  2003-01-12 12:36 Constraint_Error in arithmetic expressions Michal Nowak
@ 2003-01-12 23:37 ` Robert A Duff
  2003-01-19 13:41   ` Michal Nowak
  0 siblings, 1 reply; 4+ messages in thread
From: Robert A Duff @ 2003-01-12 23:37 UTC (permalink / raw)


Michal Nowak <vinnie@inetia.pl> writes:

> Hello,
> 
> I've been reading chapter about exceptions in Cohen's
> "Ada as a Second Language". In section 14.3.1 Constraint_Error
> there are points concerning raising exception in arithmetic
> expressions:
> 
> "In the evaluation of an arithmetic expression, an intermediate
> result that overflows may raise Constraint_Error, but it is not
> guaranteed to do so. There are several reasons for this:
> ...
> 
> o  As explained in Section 4.6, a type declared as
>       type T is range A .. B;
>    really declares T to be a subtype of some anonymous type whose
>    range includes the range A .. B. For Constraint_Error to be raised,
>    it is not enough for the subtype range A .. B to be exceeded; the
>    wider base-subtype range T'Base'First .. T'Base'Last must be
>    exceeded. Whether this happens depends on the anonymous type that
>    the compiler selects for T."
> 
> Suppose that if I declare:
>    type T is range 1 .. 200;
>    A : T := 150;
>    B : T := 150;
> the compiler may choose 1 byte (0 .. 255) or 2 bytes (0 .. 65535) for
> example, for the base subtype.

No.  "is range" declares a signed integer type, and for signed integers,
the base range is always symmetric about zero (or has an extra negative
value).  So the minimal base range the compiler can choose in this case
is -200..200.  It can choose a wider range.  Compilers usually choose a
range that is supported by the hardware.

However, there is another rule that says that compiler is always allowed
to get the right answer, instead of overflowing.

The point is, (A + B)/2 might overflow.  Any result in the base range is
guaranteed not to overflow.  Any result outside that range might
overflow.  A+B is outside -200..200, so it might overflow.

Note that overflow is different from a constraint violation.  You are
guaranteed that any assignment into an object of type T (or passing to a
parameter of type T) will raise C_E due to the constraint.  But you are
never guaranteed to get C_E due to overflow.  A correct (but
inefficient) implementation of Ada could always use multi-precision
arithmetic to get the right answer for "if (A**B)*1_000_000 > 123 then",
for example.

But who cares?  As a programmer, you want to *avoid* overflow.  So the
correct way to write the above is:

    type T_Base is 1..400;
    subtype T is T_Base range 1..200;
    A, B: T;

Then (A + B)/2 is guaranteed *not* to overflow, because T'Base =
T_Base'Base, which is at least -400..400.

The problem of course is portability: a program that works just fine on
one compiler might cause overflow on another.

- Bob



^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: Constraint_Error in arithmetic expressions
  2003-01-12 23:37 ` Robert A Duff
@ 2003-01-19 13:41   ` Michal Nowak
  2003-01-21 18:48     ` Robert A Duff
  0 siblings, 1 reply; 4+ messages in thread
From: Michal Nowak @ 2003-01-19 13:41 UTC (permalink / raw)
  To: comp.lang.ada usegroup->mailing list gateway

On 2003-01-12 at 23:37 Robert A Duff wrote:

>> Suppose that if I declare:
>>    type T is range 1 .. 200;
>>    A : T := 150;
>>    B : T := 150;
>> the compiler may choose 1 byte (0 .. 255) or 2 bytes (0 .. 65535) for
>> example, for the base subtype.
>
>No.  "is range" declares a signed integer type, and for signed integers,
>the base range is always symmetric about zero (or has an extra negative
>value).  So the minimal base range the compiler can choose in this case
>is -200..200.  It can choose a wider range.  Compilers usually choose a
>range that is supported by the hardware.

Oh, in fact, I found appropriate RM section.

Now comes another curious question -
Why the base range is symmetric about zero?
Is it because that it is for signed integer? Are there any reasons 
for it?
I'm asking, because suppose I have a 16 bit machine. 
Now I want to declare:
   type T is range 2**16 - 10 .. 2**16 - 1;

but it is not possible. However, if the base type could be in range
0 .. 2**16 - 1 it could be possible.

Thank you for your previous answer,
  - Michal


"Beyond 100,000 lines of code you
should probably be coding in Ada"
   - P. J. Plauger






^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: Constraint_Error in arithmetic expressions
  2003-01-19 13:41   ` Michal Nowak
@ 2003-01-21 18:48     ` Robert A Duff
  0 siblings, 0 replies; 4+ messages in thread
From: Robert A Duff @ 2003-01-21 18:48 UTC (permalink / raw)


Michal Nowak <vinnie@inetia.pl> writes:

> On 2003-01-12 at 23:37 Robert A Duff wrote:
> 
> >> Suppose that if I declare:
> >>    type T is range 1 .. 200;
> >>    A : T := 150;
> >>    B : T := 150;
> >> the compiler may choose 1 byte (0 .. 255) or 2 bytes (0 .. 65535) for
> >> example, for the base subtype.
> >
> >No.  "is range" declares a signed integer type, and for signed integers,
> >the base range is always symmetric about zero (or has an extra negative
> >value).  So the minimal base range the compiler can choose in this case
> >is -200..200.  It can choose a wider range.  Compilers usually choose a
> >range that is supported by the hardware.
> 
> Oh, in fact, I found appropriate RM section.
> 
> Now comes another curious question -
> Why the base range is symmetric about zero?

I don't know.  It seems like an overly hardware-oriented rule, to me.

Why not make the minimal range for T'Base be exactly T?
If you want a bigger base range, you should say so.

> Is it because that it is for signed integer? Are there any reasons 
> for it?
> I'm asking, because suppose I have a 16 bit machine.
> Now I want to declare:
>    type T is range 2**16 - 10 .. 2**16 - 1;
> 
> but it is not possible.

Well, if the compiler supports 32-bit integers on that 16-bit machine
(which is likely), then it *is* possible.  But in general, arithmetic
will then have to use 32-bit intermediate results (except in cases where
the compiler can prove it's not necessary).

>... However, if the base type could be in range
> 0 .. 2**16 - 1 it could be possible.

If the hardware supports unsigned arithmetic with efficient overflow
detection.

> Thank you for your previous answer,

You're welcome.

- Bob



^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2003-01-21 18:48 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2003-01-12 12:36 Constraint_Error in arithmetic expressions Michal Nowak
2003-01-12 23:37 ` Robert A Duff
2003-01-19 13:41   ` Michal Nowak
2003-01-21 18:48     ` Robert A Duff

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