comp.lang.ada
 help / color / mirror / Atom feed
From: Robert A Duff <bobduff@shell01.TheWorld.com>
Subject: Re: Constraint_Error in arithmetic expressions
Date: Sun, 12 Jan 2003 23:37:26 GMT
Date: 2003-01-12T23:37:26+00:00	[thread overview]
Message-ID: <wcc8yxqgcsp.fsf@shell01.TheWorld.com> (raw)
In-Reply-To: mailman.1042374422.32322.comp.lang.ada@ada.eu.org

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



  reply	other threads:[~2003-01-12 23:37 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2003-01-12 12:36 Constraint_Error in arithmetic expressions Michal Nowak
2003-01-12 23:37 ` Robert A Duff [this message]
2003-01-19 13:41   ` Michal Nowak
2003-01-21 18:48     ` Robert A Duff
replies disabled

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