From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on polar.synack.me X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00 autolearn=ham autolearn_force=no version=3.4.4 X-Google-Thread: 103376,76e8d825615718a X-Google-NewGroupId: yes X-Google-Attributes: gida07f3367d7,domainid0,public,usenet X-Google-Language: ENGLISH,ASCII Path: g2news2.google.com!postnews.google.com!s21g2000pri.googlegroups.com!not-for-mail From: Adam Beneschan Newsgroups: comp.lang.ada Subject: Re: Ada.Containers Hash function for a set of small integers Date: Mon, 26 Apr 2010 14:50:31 -0700 (PDT) Organization: http://groups.google.com Message-ID: <06f5335a-f686-4af1-893a-55517abe8d1a@s21g2000pri.googlegroups.com> References: <50701baa-7c05-450c-a42d-c699516ddc00@t14g2000prm.googlegroups.com> <0590cf17-12ea-401d-9dc3-02365139b37e@p35g2000prf.googlegroups.com> NNTP-Posting-Host: 66.126.103.122 Mime-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable X-Trace: posting.google.com 1272318631 3850 127.0.0.1 (26 Apr 2010 21:50:31 GMT) X-Complaints-To: groups-abuse@google.com NNTP-Posting-Date: Mon, 26 Apr 2010 21:50:31 +0000 (UTC) Complaints-To: groups-abuse@google.com Injection-Info: s21g2000pri.googlegroups.com; posting-host=66.126.103.122; posting-account=duW0ogkAAABjRdnxgLGXDfna0Gc6XqmQ User-Agent: G2/1.0 X-HTTP-UserAgent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; WOW64; SLCC1; .NET CLR 2.0.50727; Media Center PC 5.0; .NET CLR 3.5.21022; .NET CLR 3.5.30729; .NET CLR 3.0.30618),gzip(gfe) Xref: g2news2.google.com comp.lang.ada:11193 Date: 2010-04-26T14:50:31-07:00 List-Id: On Apr 26, 2:05=A0pm, Simon Wright wrote: > Robert A Duff writes: > > > Simon Wright writes: > > >> =A0 =A0 =A0 type M is mod 2**31; > >> =A0 =A0 =A0 Result : M :=3D 0; > >> =A0 =A0begin > >> =A0 =A0 =A0 Result :=3D 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. =A0Conversion of negative numbers > > to modular raises Constraint_Error. =A0I think that's a language design > > flaw, but not everyone agrees with me. =A0The '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 > > =A0 =A0procedure Inner (X : Integer) is > =A0 =A0 =A0 type M is mod 2**31; > =A0 =A0 =A0 Result : M; > =A0 =A0begin > > =A0 =A0 =A0 begin > =A0 =A0 =A0 =A0 =A0Result :=3D 0; > =A0 =A0 =A0 =A0 =A0Result :=3D Result xor (Integer'Pos (X) mod 2**30); > =A0 =A0 =A0 =A0 =A0-- =A0No compiler warning, but raises exception > =A0 =A0 =A0 exception > =A0 =A0 =A0 =A0 =A0when others =3D> Put_Line ("exception a"); > =A0 =A0 =A0 end; > > =A0 =A0 =A0 begin > =A0 =A0 =A0 =A0 =A0Result :=3D 0; > =A0 =A0 =A0 =A0 =A0Result :=3D Result xor (Integer'Pos (X) mod 2**31); > =A0 =A0 =A0 =A0 =A0-- =A0odd_warning.adb:20:53: warning: mod with zero di= visor > =A0 =A0 =A0 =A0 =A0-- =A0odd_warning.adb:20:53: warning: "Constraint_Erro= r" will be > =A0 =A0 =A0 =A0 =A0-- =A0 =A0raised at run time > =A0 =A0 =A0 exception > =A0 =A0 =A0 =A0 =A0when others =3D> Put_Line ("exception b"); > =A0 =A0 =A0 end; > > =A0 =A0 =A0 begin > =A0 =A0 =A0 =A0 =A0Result :=3D 0; > =A0 =A0 =A0 =A0 =A0Result :=3D Result xor M (Integer'Pos (X) mod 2**31); > =A0 =A0 =A0 =A0 =A0-- =A0No warning (and executes as I had expected) > =A0 =A0 =A0 =A0 =A0Put_Line ("result:" & M'Image (Result)); > =A0 =A0 =A0 exception > =A0 =A0 =A0 =A0 =A0when others =3D> Put_Line ("exception c"); > =A0 =A0 =A0 end; > > =A0 =A0end Inner; > > begin > > =A0 =A0Inner (-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=3D2, Right=3D31 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