## digitalmars.D.bugs - Lots of bool operations shouldn't compile

- Don Clugston (10/10) Feb 28 2006 Four examples, although it's only one bug. Almost all operations on bool...
- Oskar Linde (8/19) Feb 28 2006 According to the specification, booleans are a numeric type. true == 1
- Don Clugston (19/40) Feb 28 2006 OK, there's another bug in there, comparing an int with an imaginary
- Oskar Linde (6/51) Feb 28 2006 I fully agree.
- Don Clugston (13/15) Mar 01 2006 I just tried that in MSVC, and you're right. I didn't know that. It's
- Thomas Kuehne (63/78) Mar 02 2006 -----BEGIN PGP SIGNED MESSAGE-----
- Thomas Kuehne (35/44) Mar 02 2006 -----BEGIN PGP SIGNED MESSAGE-----
- Don Clugston (5/31) Mar 02 2006 That only gives you == and !=.
- Kyle Furlong (7/41) Mar 02 2006 One could speak of their magnitudes, I suppose.
- Don Clugston (16/62) Mar 02 2006 And then you have the problem (as in this case) that
- Kyle Furlong (2/67) Mar 02 2006 As long as its well documented and doesn't introduce bugs, why not?
- Don Clugston (5/37) Mar 02 2006 I really don't think it's a good idea (mathematicians would laugh at
- Thomas Kuehne (19/82) Mar 03 2006 -----BEGIN PGP SIGNED MESSAGE-----
- Kyle Furlong (3/14) Feb 28 2006 This kind of absurdity is exactly what Derek and others of us have been ...

Four examples, although it's only one bug. Almost all operations on bool should be disabled, but I found the ones below a little amusing. None of them should compile, but they all evaluate as "true". void main() { if (true >= ireal.nan) { writefln("This is kind of ridiculous"); } if (false >= ireal.nan) { writefln("This is kind of ridiculous"); } if (true <> -2i) { writefln("NCEG operators too ??!!"); } if (false != -2i) { writefln("and again"); } }

Feb 28 2006

Don Clugston skrev:Four examples, although it's only one bug. Almost all operations on bool should be disabled, but I found the ones below a little amusing. None of them should compile, but they all evaluate as "true". void main() { if (true >= ireal.nan) { writefln("This is kind of ridiculous"); } if (false >= ireal.nan) { writefln("This is kind of ridiculous"); } if (true <> -2i) { writefln("NCEG operators too ??!!"); } if (false != -2i) { writefln("and again"); } }According to the specification, booleans are a numeric type. true == 1 and false == 0. So this error is not specific to bool. Try s/true/1/g and s/false/0/g and you will get the same results. The first two comparisons should be false I guess since they are unordered. The other two are correct. (If it is wise to have bool as a numeric type is a different question.) /Oskar

Feb 28 2006

Oskar Linde wrote:Don Clugston skrev:OK, there's another bug in there, comparing an int with an imaginary real should also not be legal. if (1 > -2i) { assert(0); } if (1 > ireal.nan) { assert(0); } Reals and ireals cannot be compared. Ever.Four examples, although it's only one bug. Almost all operations on bool should be disabled, but I found the ones below a little amusing. None of them should compile, but they all evaluate as "true". void main() { if (true >= ireal.nan) { writefln("This is kind of ridiculous"); } if (false >= ireal.nan) { writefln("This is kind of ridiculous"); } if (true <> -2i) { writefln("NCEG operators too ??!!"); } if (false != -2i) { writefln("and again"); } }According to the specification, booleans are a numeric type. true == 1 and false == 0. So this error is not specific to bool. Try s/true/1/g and s/false/0/g and you will get the same results. The first two comparisons should be false I guess since they are unordered. The other two are correct.(If it is wise to have bool as a numeric type is a different question.)I think it's very hard to justify numeric operations on bools. (which is an _entirely_ different issue to implicit "!is null" in conditionals, I wholeheartedly support if (p), while(1){} and assert(0) ). But I note that bool b = 7; is currently disallowed, while b+=5; compiles. There's no reason to write b++, it's just letting bugs in. Write b=true instead. I hope that all such bug-breeding nonsense disappears. With a one bit integer, it wasn't clear how such things should behave (every other integral types wraps around, so b=5 should mean b=0 -- yuck!), but hopefully it can be cleared up now.

Feb 28 2006

Don Clugston skrev:Oskar Linde wrote:You are right. I didn't notice.Don Clugston skrev:OK, there's another bug in there, comparing an int with an imaginary real should also not be legal. if (1 > -2i) { assert(0); } if (1 > ireal.nan) { assert(0); } Reals and ireals cannot be compared. Ever.I fully agree. (But note that the current D bool is (sans bugs) semantically identical (as far as I can tell) to C99 and C++ bool, who both allows b+=5, et.al.) /Oskar(If it is wise to have bool as a numeric type is a different question.)I think it's very hard to justify numeric operations on bools. (which is an _entirely_ different issue to implicit "!is null" in conditionals, I wholeheartedly support if (p), while(1){} and assert(0) ). But I note that bool b = 7; is currently disallowed, while b+=5; compiles. There's no reason to write b++, it's just letting bugs in. Write b=true instead. I hope that all such bug-breeding nonsense disappears. With a one bit integer, it wasn't clear how such things should behave (every other integral types wraps around, so b=5 should mean b=0 -- yuck!), but hopefully it can be cleared up now.

Feb 28 2006

Oskar Linde wrote:(But note that the current D bool is (sans bugs) semantically identical (as far as I can tell) to C99 and C++ bool, who both allows b+=5, et.al.)I just tried that in MSVC, and you're right. I didn't know that. It's probably a legacy of the pre-bool days when ints or BOOL were used. In practice, I doubt it's really much of a problem. But there doesn't seem to be any rational reason to allow them. BTW, MSVC accepts bool b = true; b /= false; // crashes at run time with a div by zero error but gives a warning for bool b = true/false; // Can this be constant folded? What the heck does it set it to? Also accepts b/=6.5; Wonder what b/=real.nan does.

Mar 01 2006

-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Don Clugston schrieb am 2006-03-01:Oskar Linde wrote:That's interresting: b /= 6.5; // compiles b = b / 6.5; // fails to compile Bool is an integer type and thus floats are not implicitly converted to integral types. Added to DStress as http://dstress.kuehne.cn/nocompile/o/opAddAssign_19_A.d http://dstress.kuehne.cn/nocompile/o/opAddAssign_19_B.d http://dstress.kuehne.cn/nocompile/o/opAddAssign_19_C.d http://dstress.kuehne.cn/nocompile/o/opAddAssign_19_D.d http://dstress.kuehne.cn/nocompile/o/opAddAssign_19_E.d http://dstress.kuehne.cn/nocompile/o/opAddAssign_19_F.d http://dstress.kuehne.cn/nocompile/o/opAdd_09_A.d http://dstress.kuehne.cn/nocompile/o/opAdd_09_B.d http://dstress.kuehne.cn/nocompile/o/opAdd_09_C.d http://dstress.kuehne.cn/nocompile/o/opAdd_09_D.d http://dstress.kuehne.cn/nocompile/o/opAdd_09_E.d http://dstress.kuehne.cn/nocompile/o/opAdd_09_F.d http://dstress.kuehne.cn/nocompile/o/opDivAssign_19_A.d http://dstress.kuehne.cn/nocompile/o/opDivAssign_19_B.d http://dstress.kuehne.cn/nocompile/o/opDivAssign_19_C.d http://dstress.kuehne.cn/nocompile/o/opDivAssign_19_D.d http://dstress.kuehne.cn/nocompile/o/opDivAssign_19_E.d http://dstress.kuehne.cn/nocompile/o/opDivAssign_19_F.d http://dstress.kuehne.cn/nocompile/o/opDiv_14_A.d http://dstress.kuehne.cn/nocompile/o/opDiv_14_B.d http://dstress.kuehne.cn/nocompile/o/opDiv_14_C.d http://dstress.kuehne.cn/nocompile/o/opDiv_14_D.d http://dstress.kuehne.cn/nocompile/o/opDiv_14_E.d http://dstress.kuehne.cn/nocompile/o/opDiv_14_F.d http://dstress.kuehne.cn/nocompile/o/opMulAssign_19_A.d http://dstress.kuehne.cn/nocompile/o/opMulAssign_19_B.d http://dstress.kuehne.cn/nocompile/o/opMulAssign_19_C.d http://dstress.kuehne.cn/nocompile/o/opMulAssign_19_D.d http://dstress.kuehne.cn/nocompile/o/opMulAssign_19_E.d http://dstress.kuehne.cn/nocompile/o/opMulAssign_19_F.d http://dstress.kuehne.cn/nocompile/o/opMul_09_A.d http://dstress.kuehne.cn/nocompile/o/opMul_09_B.d http://dstress.kuehne.cn/nocompile/o/opMul_09_C.d http://dstress.kuehne.cn/nocompile/o/opMul_09_D.d http://dstress.kuehne.cn/nocompile/o/opMul_09_E.d http://dstress.kuehne.cn/nocompile/o/opMul_09_F.d http://dstress.kuehne.cn/nocompile/o/opSubAssign_19_A.d http://dstress.kuehne.cn/nocompile/o/opSubAssign_19_B.d http://dstress.kuehne.cn/nocompile/o/opSubAssign_19_C.d http://dstress.kuehne.cn/nocompile/o/opSubAssign_19_D.d http://dstress.kuehne.cn/nocompile/o/opSubAssign_19_E.d http://dstress.kuehne.cn/nocompile/o/opSubAssign_19_F.d http://dstress.kuehne.cn/nocompile/o/opSub_09_A.d http://dstress.kuehne.cn/nocompile/o/opSub_09_B.d http://dstress.kuehne.cn/nocompile/o/opSub_09_C.d http://dstress.kuehne.cn/nocompile/o/opSub_09_D.d http://dstress.kuehne.cn/nocompile/o/opSub_09_E.d http://dstress.kuehne.cn/nocompile/o/opSub_09_F.d Thomas -----BEGIN PGP SIGNATURE----- iD8DBQFEBq+z3w+/yD4P9tIRAu3OAJ45EVLFHn6vpmX4YjKpmEGbpV80PQCeN+Ep sBYS2snC2tpi10blB5MXRHk= =mASe -----END PGP SIGNATURE-----(But note that the current D bool is (sans bugs) semantically identical (as far as I can tell) to C99 and C++ bool, who both allows b+=5, et.al.)I just tried that in MSVC, and you're right. I didn't know that. It's probably a legacy of the pre-bool days when ints or BOOL were used. In practice, I doubt it's really much of a problem. But there doesn't seem to be any rational reason to allow them. BTW, MSVC accepts bool b = true; b /= false; // crashes at run time with a div by zero error but gives a warning for bool b = true/false; // Can this be constant folded? What the heck does it set it to? Also accepts b/=6.5; Wonder what b/=real.nan does.

Mar 02 2006

-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Don Clugston schrieb am 2006-02-28: [snip]OK, there's another bug in there, comparing an int with an imaginary real should also not be legal. if (1 > -2i) { assert(0); } if (1 > ireal.nan) { assert(0); } Reals and ireals cannot be compared. Ever.Sure you can. Floats and imaginary floats can both be implicitly promoted to complex floats. # import std.stdio; # # int main(){ # creal a = 1; # creal b = 1i; # # writefln("a: %s", a); # writefln("b: %s", b); # # writefln("1 == 1i: %s", (1 == 1i) ? true : false); # writefln("1 == 0i: %s", (1 == 0i) ? true : false); # writefln("0 == 1i: %s", (1 == 0i) ? true : false); # writefln("0 == 0i: %s", (0 == 0i) ? true : false); # # return 0; # } Thusif (1 > -2i) { assert(0); } if (1 > ireal.nan) { assert(0); }are interpreted asif (1 + 0i > 0 - 2i) { ... } if (1 + 0i > 0 + ireal.nan) { ... }The remaining question is: Is the second example unordered (due to the inan) or ordered? std.typeinfo.ti_creal._compare(creal, creal): ordered std.conv.feq(creal, creal): unordered http://www.digitalmars.com/d/float.html seems silent on this regard. Thomas -----BEGIN PGP SIGNATURE----- iD8DBQFEBqMm3w+/yD4P9tIRAlwnAJ9wYssi82l6Ompor3gKx90+8rCEhQCgycyh m5cfl2rRa9afNi1dkdL1GeM= =6QJy -----END PGP SIGNATURE-----

Mar 02 2006

Thomas Kuehne wrote:-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Don Clugston schrieb am 2006-02-28: [snip]That only gives you == and !=. <snip>OK, there's another bug in there, comparing an int with an imaginary real should also not be legal. if (1 > -2i) { assert(0); } if (1 > ireal.nan) { assert(0); } Reals and ireals cannot be compared. Ever.Sure you can. Floats and imaginary floats can both be implicitly promoted to complex floats.ThusYes, but that still doesn't work, there's no > for complex numbers. Is 2 - 3i > 3 - 2i ?if (1 > -2i) { assert(0); } if (1 > ireal.nan) { assert(0); }are interpreted asif (1 + 0i > 0 - 2i) { ... } if (1 + 0i > 0 + ireal.nan) { ... }

Mar 02 2006

Don Clugston wrote:Thomas Kuehne wrote:One could speak of their magnitudes, I suppose. creal i = 2 - 3i; creal j = 3 - 2i; real i_m = sqrt(i * complexConjugate(i)); real j_m = sqrt(j * complexConjugate(j)); but then I guess you are just comparing reals.-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Don Clugston schrieb am 2006-02-28: [snip]That only gives you == and !=. <snip>OK, there's another bug in there, comparing an int with an imaginary real should also not be legal. if (1 > -2i) { assert(0); } if (1 > ireal.nan) { assert(0); } Reals and ireals cannot be compared. Ever.Sure you can. Floats and imaginary floats can both be implicitly promoted to complex floats.ThusYes, but that still doesn't work, there's no > for complex numbers. Is 2 - 3i > 3 - 2i ?if (1 > -2i) { assert(0); } if (1 > ireal.nan) { assert(0); }are interpreted asif (1 + 0i > 0 - 2i) { ... } if (1 + 0i > 0 + ireal.nan) { ... }

Mar 02 2006

Kyle Furlong wrote:Don Clugston wrote:And then you have the problem (as in this case) that (i >= j) is true, and (i <= j) is true, but (i==j) is false. Actually, though, you _could_ bring the NCEG operators into play, and define a > b as abs(a) > abs(b) a >= b as abs(a) > abs(b) || a==b a !< b as abs(a) !< abs(b) a !<=b as abs(a) !< abs(b) && a!=b a <> b as abs(a) != abs(b) a !<>b as abs(a) == abs(b) a == b as a == b a <>=b as abs(a) <> abs(b) || a==b a!<>=b as abs(a) == abs(b) && a!=b which would even work correctly with NANs. But there's no mathematical precedent for this, AFAIK.Thomas Kuehne wrote:One could speak of their magnitudes, I suppose. creal i = 2 - 3i; creal j = 3 - 2i; real i_m = sqrt(i * complexConjugate(i)); real j_m = sqrt(j * complexConjugate(j)); but then I guess you are just comparing reals.-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Don Clugston schrieb am 2006-02-28: [snip]That only gives you == and !=. <snip>ThusYes, but that still doesn't work, there's no > for complex numbers. Is 2 - 3i > 3 - 2i ?if (1 > -2i) { assert(0); } if (1 > ireal.nan) { assert(0); }are interpreted asif (1 + 0i > 0 - 2i) { ... } if (1 + 0i > 0 + ireal.nan) { ... }

Mar 02 2006

Don Clugston wrote:Kyle Furlong wrote:As long as its well documented and doesn't introduce bugs, why not?Don Clugston wrote:And then you have the problem (as in this case) that (i >= j) is true, and (i <= j) is true, but (i==j) is false. Actually, though, you _could_ bring the NCEG operators into play, and define a > b as abs(a) > abs(b) a >= b as abs(a) > abs(b) || a==b a !< b as abs(a) !< abs(b) a !<=b as abs(a) !< abs(b) && a!=b a <> b as abs(a) != abs(b) a !<>b as abs(a) == abs(b) a == b as a == b a <>=b as abs(a) <> abs(b) || a==b a!<>=b as abs(a) == abs(b) && a!=b which would even work correctly with NANs. But there's no mathematical precedent for this, AFAIK.if (1 > -2i) { assert(0); } if (1 > ireal.nan) { assert(0); }are interpreted asif (1 + 0i > 0 - 2i) { ... } if (1 + 0i > 0 + ireal.nan) { ... }

Mar 02 2006

I really don't think it's a good idea (mathematicians would laugh at us). If you want to compare the magnitudes, you should say so. But, I find it interesting that the NCEG operators allow you to define meaningful ordering comparisons for quantities for which a strict weak ordering does not exist.As long as its well documented and doesn't introduce bugs, why not?And then you have the problem (as in this case) that (i >= j) is true, and (i <= j) is true, but (i==j) is false. Actually, though, you _could_ bring the NCEG operators into play, and define a > b as abs(a) > abs(b) a >= b as abs(a) > abs(b) || a==b a !< b as abs(a) !< abs(b) a !<=b as abs(a) !< abs(b) && a!=b a <> b as abs(a) != abs(b) a !<>b as abs(a) == abs(b) a == b as a == b a <>=b as abs(a) <> abs(b) || a==b a!<>=b as abs(a) == abs(b) && a!=b which would even work correctly with NANs. But there's no mathematical precedent for this, AFAIK.Yes, but that still doesn't work, there's no > for complex numbers. Is 2 - 3i > 3 - 2i ?One could speak of their magnitudes, I suppose. creal i = 2 - 3i; creal j = 3 - 2i; real i_m = sqrt(i * complexConjugate(i)); real j_m = sqrt(j * complexConjugate(j)); but then I guess you are just comparing reals.

Mar 02 2006

-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Kyle Furlong schrieb am 2006-03-03:Don Clugston wrote:http://www.digitalmars.com/d/float.html # Floating Point Comparisons # # In addition to the usual < <= > >= == != comparison operators, D adds # more that are specific to floating point. These are !<>= <> <>= !<= !< # !>= !> !<> and match the semantics for the NCEG extensions to C. creal/cdouble/cfloat are "Floating Point Types" and "Floating Point Comparisons" are those stated by NCEG. So what does NCEG say on compairing _Complex? (Couldn't find any useful NCEG documents ...) Thomas -----BEGIN PGP SIGNATURE----- iD8DBQFECHri3w+/yD4P9tIRApwuAJ46SuFsHnytm8aVfp4/w9fnt7Le4gCfSb6F Zu/XOm3qGyAJ14TyVUKQBv4= =WDhO -----END PGP SIGNATURE-----Kyle Furlong wrote:As long as its well documented and doesn't introduce bugs, why not?Don Clugston wrote:And then you have the problem (as in this case) that (i >= j) is true, and (i <= j) is true, but (i==j) is false. Actually, though, you _could_ bring the NCEG operators into play, and define a > b as abs(a) > abs(b) a >= b as abs(a) > abs(b) || a==b a !< b as abs(a) !< abs(b) a !<=b as abs(a) !< abs(b) && a!=b a <> b as abs(a) != abs(b) a !<>b as abs(a) == abs(b) a == b as a == b a <>=b as abs(a) <> abs(b) || a==b a!<>=b as abs(a) == abs(b) && a!=b which would even work correctly with NANs. But there's no mathematical precedent for this, AFAIK.Thomas Kuehne wrote:One could speak of their magnitudes, I suppose. creal i = 2 - 3i; creal j = 3 - 2i; real i_m = sqrt(i * complexConjugate(i)); real j_m = sqrt(j * complexConjugate(j)); but then I guess you are just comparing reals.Don Clugston schrieb am 2006-02-28: [snip]That only gives you == and !=. <snip>if (1 > -2i) { assert(0); } if (1 > ireal.nan) { assert(0); }are interpreted asif (1 + 0i > 0 - 2i) { ... } if (1 + 0i > 0 + ireal.nan) { ... }

Mar 03 2006

Don Clugston wrote:

Feb 28 2006