comp.lang.ada
 help / color / mirror / Atom feed
From: Adam Beneschan <adam@irvine.com>
Subject: Re: Ada.Containers Hash function for a set of small integers
Date: Mon, 26 Apr 2010 14:50:31 -0700 (PDT)
Date: 2010-04-26T14:50:31-07:00	[thread overview]
Message-ID: <06f5335a-f686-4af1-893a-55517abe8d1a@s21g2000pri.googlegroups.com> (raw)
In-Reply-To: m2zl0p9b7i.fsf@pushface.org

On Apr 26, 2:05 pm, Simon Wright <si...@pushface.org> wrote:
> Robert A Duff <bobd...@shell01.TheWorld.com> writes:
>
> > Simon Wright <si...@pushface.org> writes:
>
> >>       type M is mod 2**31;
> >>       Result : M := 0;
> >>    begin
> >>       Result := Result xor Integer'Pos (I.A);
>
> >> and, before anyone rushes to check it out, yes, it fails with
> >> negative values and I'm about to file a bug against it.
>
> > I don't think that's a compiler bug.  Conversion of negative numbers
> > to modular raises Constraint_Error.  I think that's a language design
> > flaw, but not everyone agrees with me.  The 'Mod attribute works
> > around the problem.
>
> No, I meant a bug against my code generator!
>
> On the other hand, I found some strange behaviour with GNAT GPL 2009
> (and GCC 4.5.0) while investigating possible solutions:
>
> ------------------------------------------------------------------------
> with Ada.Text_IO; use Ada.Text_IO;
>
> procedure Odd_Warning is
>
>    procedure Inner (X : Integer) is
>       type M is mod 2**31;
>       Result : M;
>    begin
>
>       begin
>          Result := 0;
>          Result := Result xor (Integer'Pos (X) mod 2**30);
>          --  No compiler warning, but raises exception
>       exception
>          when others => Put_Line ("exception a");
>       end;
>
>       begin
>          Result := 0;
>          Result := Result xor (Integer'Pos (X) mod 2**31);
>          --  odd_warning.adb:20:53: warning: mod with zero divisor
>          --  odd_warning.adb:20:53: warning: "Constraint_Error" will be
>          --    raised at run time
>       exception
>          when others => Put_Line ("exception b");
>       end;
>
>       begin
>          Result := 0;
>          Result := Result xor M (Integer'Pos (X) mod 2**31);
>          --  No warning (and executes as I had expected)
>          Put_Line ("result:" & M'Image (Result));
>       exception
>          when others => Put_Line ("exception c");
>       end;
>
>    end Inner;
>
> begin
>
>    Inner (-1);
>
> end Odd_Warning;
> ------------------------------------------------------------------------
>
> The second block's compiler warning is strange, especially the part
> about the zero divisor. The Aonix ObjectAda 7.2 compiler gives a very
> similar warning referring to 95LRM4.5.5(22), and gives an error at the
> third block (95LRM4.9(35)).

The warning looks correct to me.  The way the expression is
constructed in the second block, all of the operators have operands of
type M (except for the right operand of "**").  This means that you're
using "**" with the definition

   function "**" (Left : M; Right : Integer) return M;

And modular operations wrap around.  The result of the above operator
with arguments Left=2, Right=31 is therefore 0, since the range of M
is 0 .. 2**31-1.

In the third block, the type conversion to M changes everything; the
argument of this type conversion can be anything that works (as
opposed to the second block, in which the right side must be an
expression of type M).  Since the type of Integer'Pos(X) is a
universal integer, the end result is that the operators inside the
type conversion are interpreted as being the operations of the
"root_integer" type.  Whether the error message is correct, incorrect,
or implementation-dependent, I'm not sure without further study, but I
suspect that it may be implementation-dependent and may depend on what
base ranges the implementation has chosen for its built-in integer
types.

In any case, unless you're trying to develop code that compiles with
an Ada95 compiler, I'd prefer to use 'Mod over Unchecked_Conversion.
The whole purpose of 'Mod was to eliminate the need for
Unchecked_Conversion in cases like this, since it was impossible to
write "normal" code that would do the computation correctly.

                               -- Adam



  reply	other threads:[~2010-04-26 21:50 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-04-22 23:26 Ada.Containers Hash function for a set of small integers Michael R
2010-04-23  1:39 ` John B. Matthews
2010-04-23 21:39 ` Simon Wright
2010-04-23 22:47   ` Michael R
2010-04-24 11:28     ` Simon Wright
2010-04-26 18:37       ` Robert A Duff
2010-04-26 21:05         ` Simon Wright
2010-04-26 21:50           ` Adam Beneschan [this message]
2010-04-27  4:50             ` AdaMagica
2010-04-27 19:04               ` Simon Wright
2010-04-27 19:08             ` Simon Wright
2010-04-23 23:08   ` Jeffrey R. Carter
2010-04-26 15:33   ` Warren
2010-04-26 18:14     ` Jeffrey R. Carter
2010-04-26 18:32       ` Charmed Snark
2010-05-05  4:29   ` Yannick Duchêne (Hibou57)
2010-05-06 15:46     ` Warren
replies disabled

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