[comp.lang.ada] Fixed times Integer

Marc.Graham@SEI.CMU.EDU (08/29/90)

Section 4.5.5 allows multiplication of an object of any fixed point
type by an object of "the predefined type INTEGER" (Standard.Integer).
Consider the following:
------------
procedure junk is

    type blarb is delta 0.1 range 0.0 .. 32769.0;
    thing : blarb;
    
begin
    if thing * 32767 > thing * 32768 then
    	null;
    end if;
end junk;
----------
My Sun Alsys compliers complains in the following way:
------
        8     if thing * 32767 > thing * 32768 then
                                         <-1->     
  1    *EXP This value is outside the range of the target type.  NUMERIC_ERROR
           will be raised here at run time.
----

This complier will do 32-bit arithmetic, but Integer is 16 bits.

Questions: 1) Is the Alsys complier correct in its complaint? (I think
it is.) 

2) Is there an Ada commentary or such to the effect: "Of course, when
the manual *says* INTEGER it doesn't really *mean* INTEGER, ...."?

NCOHEN@IBM.COM ("Norman H. Cohen") (08/30/90)

Marc Graham questions the message indicating that NUMERIC_ERROR will
be raised at the point of the numeric literal 32768 in the following
program:

     procedure junk is

         type blarb is delta 0.1 range 0.0 .. 32769.0;
         thing : blarb;

     begin
         if thing * 32767 > thing * 32768 then
                 null;
         end if;
     end junk;

Technically, the exception is raised not by the multiplication, but by
the implicit conversion of the universal integer value 32,768 to type
Integer (which is 16 bits in Marc's implementation).  This is explicitly
justified by RM 3.5.4(10).  However, an implementation is allowed to be
more reasonable.  That same paragraph goes on to say, "However, an
implementation is not required to raise the exception NUMERIC_ERROR if
the operation is part of a larger expression whose result can be computed
correctly, as described in section 11.6."  (The full rule is given in
RM 11.6(5), which I will not quote here because all readings of that
paragraph generate more questions than they answer.)  In the example
above, there are values of THING for which the enclosing expression can
be successfully evaluated, so the compiler is not being as helpful as
it could be.  I wonder how it treats

   I: Integer := -32768;

(in which evaluation of the initial value technically consists of
conversion of the universal_integer value 32768 to type Integer
followed by invocation of the negation operator for type Integer).

Marc.Graham@SEI.CMU.EDU (08/31/90)

Norm Cohen is correct in his description of why the Alsys compiler
behaves the way it does. (To refresh your memory, the question
concerns the following Ada text and the accompanying warning.)


------------
procedure junk is

    type blarb is delta 0.1 range 0.0 .. 32769.0;
    thing : blarb;
    
begin
    if thing * 32767 > thing * 32768 then
    	null;
    end if;
end junk;
----------
My Sun Alsys compliers complains in the following way:
------
        8     if thing * 32767 > thing * 32768 then
                                         <-1->     
  1    *EXP This value is outside the range of the target type.  NUMERIC_ERROR
           will be raised here at run time.
----


Dr. Cohen failed to answer my real question, which is not surprising,
considering that I failed to ask it. So my real question is:

Why does LRM section 4.5.5, paragraph 10, use Standard.Integer instead
of either UNIVERSAL_INTEGER (allowing multiplcation and division of
fixeds by integer literals or named numbers) or "any integer type"
(allowing those operations for any integer and fixed objects)? Those
two alternatives are easily remembered and explained. The situation in
4.5.5 (10) allows for some, but not all, literals and some, but not
all, non-literals. Is there any rhyme or reason to this?

Marc H. Graham                    Software Engineering Institute
marc@sei.cmu.edu                  Carnegie Mellon University
(412) 268 7784                    Pittsburgh, PA   15213