From: Simon Wright on 26 Apr 2010 17:05 Robert A Duff <bobduff(a)shell01.TheWorld.com> writes: > Simon Wright <simon(a)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)). I think my route will be via unchecked conversion, if I don't decide that it's a feature - in 10 years of use no one has needed to use a negative value as a component of a hash.
From: Adam Beneschan on 26 Apr 2010 17:50 On Apr 26, 2:05 pm, Simon Wright <si...(a)pushface.org> wrote: > Robert A Duff <bobd...(a)shell01.TheWorld.com> writes: > > > Simon Wright <si...(a)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
From: AdaMagica on 27 Apr 2010 00:50 > > 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; > about the zero divisor. The Aonix ObjectAda 7.2 compiler ... > gives an error at the third block (95LRM4.9(35)). I'm no language lawyer, but I'll give it a try. RM95 4.9(35): If the expression is not part of a larger static expression, then its value shall be within the base range of its expected type. Otherwise, the value may be arbitrarily large or small. RM TC1 AM1 4.9(35/2) {AI95-00269-01} If the expression is not part of a larger static expression *and the expression is expected to be of a single specific type*, then its value shall be within the base range of its expected type. Otherwise, the value may be arbitrarily large or small. Since Aonix quotes 95RM4.9(35), it must be a pure Ada95 compiler. 2**31 is not part or a larger static expression. The further condition of being of a single specific type (which is not the case here, the expected type is any integer type) was added later. So Aonix is correct, and so is GNAT, if the latter is new enough to obey AM1.
From: Simon Wright on 27 Apr 2010 15:04 AdaMagica <christoph.grein(a)eurocopter.com> writes: > Since Aonix quotes 95RM4.9(35), it must be a pure Ada95 compiler. Thanks for the analysis. The '95' in that quote was actually me. But since the compiler binaries are no later than Feb 2000 I think your conclusion is correct!
From: Simon Wright on 27 Apr 2010 15:08 Adam Beneschan <adam(a)irvine.com> writes: > 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. Ada95 it is .. though I could actually change now with no impact on the current user project, which is not going to migrate.
First
|
Prev
|
Next
|
Last
Pages: 1 2 3 4 Prev: How to access this package written in C? Next: integer questia |