[fpc-devel] bug: Inc(v,i)/Dec(v,i)

Marcel Martin mm10 at ellipsa.net
Sun Jul 10 18:10:13 CEST 2005


Hans-Peter Diettrich a écrit :
> So we have to find out what is *correct*.

When I wrote "correct code", I meant "not only the code that
gives the correct result but also the code that correctly
computes it".

>>If I declare a constant as an unsigned integer, if I wrote my
>>code assuming it is an unsigned integer and if, suddenly,
>>I decide to change that, of course, I may expect some problems.
> 
> 
> Why should one expect problems when incrementing or decrementing an
> value, maybe signed or unsigned?

We are talking about overflows. If I wrote some code that
depends on the possible overflows of an instance of type
Longword and if I change the type of the variable to Longint
without changing the code, I may expect problems.

>>Unexpected overflows? The overflows occur or not according to
>>simple rules, perfectly defined, which ones depend on the types
>>of the operands.
> 
> 
> Unexpected as depending on the values, not on the types. When the ranges
> of the possible operands are known, it's also known whether an overflow
> can occur in computations with these operands. 

But overflows cannot be unexpected. If x is a Longword and
if x > 0, Inc(x,-1) will raise an overflow. And this is not
unexpected.

>> > From
>>
>>>the mathematical viewpoint +(+1) and -(-1) is perfectly equivalent, as
>>>is +(-1) and -(+1).
>>
>>Computationally, this is not equivalent.
>>+(-1) -> add eax, $ffffffff
>>-(+1) -> sub eax, $00000001
>>And at this point, even if we know the content of eax before the
>>operation, we cannot know if there is or not an overflow without
>>knowing the type of the integer contained in eax.
> 
> 
> Since the hardware cannot know whether $ffffffff is a huge unsigned
> number, or a small signed number, a possibly thrown or indicated
> overflow from above instructions is meaningless. This is why a proper
> and unoptimized implementation must extend values of different
> signedness to the next bigger type, so that the calculation cannot
> produce an overflow.

That's what FPC does when such a bigger type exists. But are
we talking about that?
This thread is about "since the resulting x, after Inc(x,-1),
is in the range of x, the compiler should code Dec(x,1)". No,
it shouldn't. When a programmer writes "Inc", he explicitely
asks the compiler to code an addition and not a subtraction.
If, in "Inc(x,-1)", x is a Longword, the compiler should
regard "-1" as a Longword or signals a problem. In no case,
the compiler should decide not to raise an overflow because
the result of an operation is in the range of the destination
variable. Overflows depend on operations not on results.

>>Moreover, when programming, mathematical considerations have to
>>be handled with care. Mathematically, (x = -x) -> (x = 0).
>>Computationally, this is wrong (because the computer doesn't work
>>over the ring Z but over a ring Z/2^kZ). If x is a Longint and
>>if x = -x, either x = 0 or x = -2^31.
> 
> 
> Bad example. 

Indeed? :-)

 > In 2's complement both 0 and -2^31 have no counterpart of
> the opposite sign, whereas in 2-1 complement (sorry, don't know the
> English term) the negative values are represented by the bitwise
> complement of the positive values. When there exists no representation
> of -(-2^31), you cannot perform an comparison with that value.
> 
> 
>>Try this
>>
>>   x : Longint;
>>   ...
>>   x := Longint($80000000); // x := -2^31
>>   WriteLn(IntToStr(x));
>>   x := -x;
>>   WriteLn(IntToStr(x));
>>
>>(And this is not a bug. This is a consequence of the 2-complement
>>representation of signed integers.)
> 
> 
> It is a bug. 

We have a big, BIG, communication problem. When I write,
2^31 = -2^31 is a consequence of the representation and not a
bug and when you wrote it is a bug since it should raise a
range check error, are we talking of the same thing? ;-)

Moreover, since you use mathematical viewpoints, I don't
see where is the problem for you : mathematically, it is
true that 2^(k-1) = -2^(k-1) (mod 2^k).

> As outlined before, the above assignment of x:=-x should
> raise an range check error. A comparison of x=-x will return False, in
> the Int64 range.

Not with FPC. (Moreover, I didn't make comparisons, I only
used ":=" and "-".)

> The expression Longint($80000000) is questionable because, in the strict
> sense, it forces the compiler to perform an illegal operation, which
> only happens to produce an in-range value on specific machines.

Use this "x := -(1 shl 31);" if you prefer. What does it change
for the purpose of the example?

mm




More information about the fpc-devel mailing list