digitalmars.D - Error on negating unsigned types
- Johan Engelen (31/31) Jul 11 2017 The Weka folks would like to see a compile error on negating
- Johan Engelen (5/7) Jul 11 2017 Also this nice hackery would need a workaround:
- Johan Engelen (5/12) Jul 11 2017 http://www.exploringbinary.com/ten-ways-to-check-if-an-integer-is-a-powe...
- Johan Engelen (4/17) Jul 11 2017 Codegen is the same for both: https://godbolt.org/g/JiHiEe
- Guillaume Chatelet (2/20) Jul 11 2017 Interestingly returning a bool saves one register and a XOR.
- Daniel Kozak via Digitalmars-d (11/19) Jul 11 2017 I belive this is a bug or it should be fixed and do same as C does.
- Eyal Lotem (7/9) Jul 11 2017 The error would be great!
- Walter Bright (3/10) Jul 11 2017 The behavior should be the same.
- ketmar (4/14) Jul 11 2017 so, you want to change promotion rules? just to clarify the things, how
- Andrei Alexandrescu (2/5) Jul 12 2017 A compelling argument is that the rule exposed two bugs in Phobos. -- An...
- Steven Schveighoffer (18/26) Jul 12 2017 Those aren't bugs, they are false negatives (pun?).
- Johan Engelen (12/14) Jul 12 2017 It's a trade-off between nuisance in some cases (the Phobos ones
- Steven Schveighoffer (43/58) Jul 13 2017 My only point is with Andrei's assertion that it "exposed two bugs in
- Walter Bright (8/10) Jul 12 2017 The particular issue you were having appears to be a bug in the compiler...
The Weka folks would like to see a compile error on negating unsigned types: ``` uint total = 0; void add(int x) { total += x; } ubyte popCount() { return 5; } add(popCount()); add(-popCount()); writeln(total); // <-- what does this print? (behavior is different from C) ``` After adding the error, a few places in Phobos error out. For example: ``` (std.format.formatIntegral) T arg = val; immutable negative = (base == 10 && arg < 0); if (negative) { arg = -arg; } ``` ``` (std.conv.toTextRange) T value; bool negative = value < 0; Unqual!(Unsigned!T) v = negative ? -value : value; ``` So, adding the error may be nice, but it would make generic code a little more verbose. Ideas? People OK with that? cheers, Johan
Jul 11 2017
On Tuesday, 11 July 2017 at 19:46:00 UTC, Johan Engelen wrote:The Weka folks would like to see a compile error on negating unsigned types:Also this nice hackery would need a workaround: ``` if ((y&(-y))==y) ```
Jul 11 2017
On Tuesday, 11 July 2017 at 19:57:06 UTC, Johan Engelen wrote:On Tuesday, 11 July 2017 at 19:46:00 UTC, Johan Engelen wrote:http://www.exploringbinary.com/ten-ways-to-check-if-an-integer-is-a-power-of-two-in-c/ "The two’s complement of x is computed with ~x + 1, which inverts the bits of x and adds 1 (~x + 1 is equivalent to -x, but negation is technically illegal for an unsigned integer)."The Weka folks would like to see a compile error on negating unsigned types:Also this nice hackery would need a workaround: ``` if ((y&(-y))==y) ```
Jul 11 2017
On Tuesday, 11 July 2017 at 20:02:07 UTC, Johan Engelen wrote:On Tuesday, 11 July 2017 at 19:57:06 UTC, Johan Engelen wrote:Codegen is the same for both: https://godbolt.org/g/JiHiEe So Phobos's `if ((y&(-y))==y)` can be rewritten to `if ((y&(~y+1))==y)` without consequence.On Tuesday, 11 July 2017 at 19:46:00 UTC, Johan Engelen wrote:http://www.exploringbinary.com/ten-ways-to-check-if-an-integer-is-a-power-of-two-in-c/ "The two’s complement of x is computed with ~x + 1, which inverts the bits of x and adds 1 (~x + 1 is equivalent to -x, but negation is technically illegal for an unsigned integer)."The Weka folks would like to see a compile error on negating unsigned types:Also this nice hackery would need a workaround: ``` if ((y&(-y))==y) ```
Jul 11 2017
On Tuesday, 11 July 2017 at 20:05:43 UTC, Johan Engelen wrote:On Tuesday, 11 July 2017 at 20:02:07 UTC, Johan Engelen wrote:Interestingly returning a bool saves one register and a XOR.On Tuesday, 11 July 2017 at 19:57:06 UTC, Johan Engelen wrote:Codegen is the same for both: https://godbolt.org/g/JiHiEe So Phobos's `if ((y&(-y))==y)` can be rewritten to `if ((y&(~y+1))==y)` without consequence.On Tuesday, 11 July 2017 at 19:46:00 UTC, Johan Engelen wrote:http://www.exploringbinary.com/ten-ways-to-check-if-an-integer-is-a-power-of-two-in-c/ "The two’s complement of x is computed with ~x + 1, which inverts the bits of x and adds 1 (~x + 1 is equivalent to -x, but negation is technically illegal for an unsigned integer)."[...]Also this nice hackery would need a workaround: ``` if ((y&(-y))==y) ```
Jul 11 2017
I belive this is a bug or it should be fixed and do same as C does. import std.stdio; void main() { uint total = 0; byte popCount() { return 5; } writeln(total + popCount() - popCount()); } works as expected On Tue, Jul 11, 2017 at 9:57 PM, Johan Engelen via Digitalmars-d < digitalmars-d puremagic.com> wrote:On Tuesday, 11 July 2017 at 19:46:00 UTC, Johan Engelen wrote:The Weka folks would like to see a compile error on negating unsigned types:Also this nice hackery would need a workaround: ``` if ((y&(-y))==y) ```
Jul 11 2017
On Tuesday, 11 July 2017 at 19:46:00 UTC, Johan Engelen wrote:The Weka folks would like to see a compile error on negating unsigned types:The error would be great! I've filed a bug yesterday: https://issues.dlang.org/show_bug.cgi?id=17633 In it I asked to change the result type, but an error works just as well. Unsigned negation bit us with costly bugs multiple times so far.
Jul 11 2017
On 7/11/2017 12:46 PM, Johan Engelen wrote:uint total = 0; void add(int x) { total += x; } ubyte popCount() { return 5; } add(popCount()); add(-popCount()); writeln(total); // <-- what does this print? (behavior is different from C)The behavior should be the same. https://issues.dlang.org/show_bug.cgi?id=17637
Jul 11 2017
Walter Bright wrote:On 7/11/2017 12:46 PM, Johan Engelen wrote:so, you want to change promotion rules? just to clarify the things, how *exactly* you want new rules to work, and what will happen with `byte a; a = -a;`, and why?uint total = 0; void add(int x) { total += x; } ubyte popCount() { return 5; } add(popCount()); add(-popCount()); writeln(total); // <-- what does this print? (behavior is different from C)The behavior should be the same. https://issues.dlang.org/show_bug.cgi?id=17637
Jul 11 2017
On 07/11/2017 03:46 PM, Johan Engelen wrote:So, adding the error may be nice, but it would make generic code a little more verbose. Ideas? People OK with that?A compelling argument is that the rule exposed two bugs in Phobos. -- Andrei
Jul 12 2017
On 7/12/17 11:00 AM, Andrei Alexandrescu wrote:On 07/11/2017 03:46 PM, Johan Engelen wrote:Those aren't bugs, they are false negatives (pun?). ``` (std.format.formatIntegral) T arg = val; immutable negative = (base == 10 && arg < 0); if (negative) // will always be false for unsigned types { arg = -arg; } ``` ``` (std.conv.toTextRange) T value; bool negative = value < 0; // also will always be false Unqual!(Unsigned!T) v = negative ? -value : value; ``` Not sure if the compiler can figure that out. Which means this may cause a bunch of nuisance errors. -SteveSo, adding the error may be nice, but it would make generic code a little more verbose. Ideas? People OK with that?A compelling argument is that the rule exposed two bugs in Phobos. -- Andrei
Jul 12 2017
On Wednesday, 12 July 2017 at 20:12:03 UTC, Steven Schveighoffer wrote:... Which means this may cause a bunch of nuisance errors.It's a trade-off between nuisance in some cases (the Phobos ones can be solved with val = abs(val), or with static if), and possibly catching bugs in other cases. We can compare this with negation of a bool and subtracting a bool: ``` bool b; auto x = 1 - b; // allowed auto y = -b; // not allowed ```
Jul 12 2017
On 7/12/17 5:24 PM, Johan Engelen wrote:On Wednesday, 12 July 2017 at 20:12:03 UTC, Steven Schveighoffer wrote:My only point is with Andrei's assertion that it "exposed two bugs in Phobos". In terms of the trade-off, it looks like this is just a straight bug that should be fixed. If the behavior goes back to being like C, is it still so bad that it needs an error? My testing: import std.stdio; void main() { ubyte x = 5; int y = -x; writeln(y); uint t = 0; t += x; writeln(t); t += y; writeln(t); } outputs: 251 5 256 In C: #include <stdio.h> int main() { unsigned char x = 5; int y = -x; printf("%d\n", y); unsigned int t = 0; t += x; printf("%u\n", t); t += y; printf("%u\n", t); return 0; } outputs: -5 5 0 The C behavior seems fine to me. -Steve... Which means this may cause a bunch of nuisance errors.It's a trade-off between nuisance in some cases (the Phobos ones can be solved with val = abs(val), or with static if), and possibly catching bugs in other cases. We can compare this with negation of a bool and subtracting a bool: ``` bool b; auto x = 1 - b; // allowed auto y = -b; // not allowed ```
Jul 13 2017
On 7/11/2017 12:46 PM, Johan Engelen wrote:So, adding the error may be nice, but it would make generic code a little more verbose.The particular issue you were having appears to be a bug in the compiler (I already filed it as a bug report). Being a bug, we need more evidence that adding an error for -u is compelling. There really isn't a comprehensive solution for mistakes using unsigned. Some languages deal with the issue by not having an unsigned type at all (Java). At some level, it's necessary to just be aware of different integer sizes, integral promotion rules, what happens with overflows, and sign.
Jul 12 2017