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
_______________________________________________
fpc-devel maillist - fpc-devel@lists.freepascal.org
http://lists.freepascal.org/mailman/listinfo/fpc-devel