digitalmars.D.learn - Strange behaviour trying to bitwise or two negative ints into a long
- Deewiant <deewiant.doesnotlike.spam gmail.com> May 11 2007
- Thomas Kuehne <thomas-dloop kuehne.cn> May 11 2007
- Deewiant <deewiant.doesnotlike.spam gmail.com> May 12 2007
import std.stdio;
int a = -1;
int b = -2;
void main() {
writefln(" a: 0b%064b", a);
writefln(" b: 0b%064b", cast(long)b);
writefln(" b << 32: 0b%064b", cast(long)b << 32);
writefln("| a : 0b%064b", cast(long)b << 32 | a);
writefln("| a & : 0b%064b", cast(long)b << 32 | (a & 0xffff_ffff));
writefln("| cast a: 0b%064b", cast(long)b << 32 | cast(uint)a);
/+ using values copied from the outputs of the first two writeflns above +/
writefln("binconst: 0b%064b",
0b1111111111111111111111111111111111111111111111111111111111111110 << 32 |
0b0000000000000000000000000000000011111111111111111111111111111111);
}
Why do the last writeflns output a different number than the plain cast(long)b
<< 32 | a one? Why do I need the cast or bitwise and?
I was originally going to file a bug but I think I'm just misunderstanding
something fundamental.
--
Remove ".doesnotlike.spam" from the mail address.
May 11 2007
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Deewiant schrieb am 2007-05-11:import std.stdio; int a = -1; int b = -2; void main() { writefln(" a: 0b%064b", a); writefln(" b: 0b%064b", cast(long)b); writefln(" b << 32: 0b%064b", cast(long)b << 32); writefln("| a : 0b%064b", cast(long)b << 32 | a); writefln("| a & : 0b%064b", cast(long)b << 32 | (a & 0xffff_ffff)); writefln("| cast a: 0b%064b", cast(long)b << 32 | cast(uint)a); /+ using values copied from the outputs of the first two writeflns above +/ writefln("binconst: 0b%064b", 0b1111111111111111111111111111111111111111111111111111111111111110 << 32 | 0b0000000000000000000000000000000011111111111111111111111111111111); } Why do the last writeflns output a different number than the plain cast(long)b << 32 | a one? Why do I need the cast or bitwise and? I was originally going to file a bug but I think I'm just misunderstanding something fundamental.
There is a bug as well as a misunderstanding. # import std.stdio; # # int thirty_one = 31; # int thirty_two = 32; # int thirty_three = 33; # int two_neg = -2; # int four_neg = -4; # int i = -1; # uint u = -1; # # TypeInfo type_info(...){ # return _arguments[0]; # } # void info(char[] exp)(char[] comment = null){ # writef("0b%064b ", mixin(exp)); # writef("%s", typeof(mixin(exp)).stringof); # mixin("writefln(\"\t%s\", \"" ~ exp ~ "\");"); # if(comment.length){ # writefln("\t%s", comment); # } # } # # void main() { # info!("i"); # info!("u"); # info!("two_neg"); # writefln(); # info!("cast(long)two_neg << 32 | i"); # info!("cast(long)two_neg << 32 | u")("Why do they differ?"); # writefln(); # info!("two_neg << 32")("Huh? Let's try that again:"); # info!("two_neg"); # info!("two_neg << thirty_two"); # info!("(two_neg << 31) << 1"); # info!("(two_neg << 31) << 2"); # info!("two_neg << thirty_three"); # writefln(); # writefln("%s", "issue: shifting is implemented as\n" # "\t\tx << (shift % (sizeof(x) * 8))\n" # "\tinstead of\n" # "\t\tx << ((shift >= (sizeof(x) * 8)) ? (0) : (shift))"); # writefln("at least for cases where the shift width is known at compile time accepting \"sizeof(x) * 8\" is a bug"); # writefln(); # writefln("Let's try another approach:"); # info!("cast(long)two_neg << 32 | i"); # info!("cast(long)two_neg << 32 | u"); # info!("(cast(long)two_neg) << 32 | i"); # info!("(cast(long)two_neg) << 32 | u"); # info!("((cast(long)two_neg) << 32) | i"); # info!("((cast(long)two_neg) << 32) | u"); # info!("((cast(long)two_neg) << 32) | (cast(long)i)"); # info!("((cast(long)two_neg) << 32) | (cast(long)u)"); # info!("((cast(long)two_neg) << 32) | (cast(long)i)"); # info!("((cast(long)two_neg) << 32) | (cast(long)u)"); # writefln(); # info!("(cast(long)two_neg) << 32"); # info!("cast(long) 0xFFFFFFFE_00000000L"); # info!("(cast(long) 0xFFFFFFFE_00000000L) | i"); # info!("(cast(long) 0xFFFFFFFE_00000000L) | u"); # info!("cast(long) i"); # info!("cast(long) u"); # writefln(); # writefln("I hope the 2 lines below make sense now"); # info!("cast(long)two_neg << 32 | i"); # info!("cast(long)two_neg << 32 | u"); # } # Thomas -----BEGIN PGP SIGNATURE----- iD8DBQFGRPj7LK5blCcjpWoRAllcAJ9Hk6eFxiqmxcrpLmjeFwqSy0+P9ACbBWUR zWVUdAXJdn1VJFkdf5B7q4o= =if/F -----END PGP SIGNATURE-----
May 11 2007
Thomas Kuehne wrote:Deewiant schrieb am 2007-05-11:import std.stdio;
int a = -1; int b = -2;
void main() { writefln(" a: 0b%064b", a); writefln(" b: 0b%064b", cast(long)b); writefln(" b << 32: 0b%064b", cast(long)b << 32); writefln("| a : 0b%064b", cast(long)b << 32 | a); writefln("| a & : 0b%064b", cast(long)b << 32 | (a & 0xffff_ffff)); writefln("| cast a: 0b%064b", cast(long)b << 32 | cast(uint)a);
/+ using values copied from the outputs of the first two writeflns above +/ writefln("binconst: 0b%064b", 0b1111111111111111111111111111111111111111111111111111111111111110 << 32 | 0b0000000000000000000000000000000011111111111111111111111111111111); }
Why do the last writeflns output a different number than the plain cast(long)b << 32 | a one? Why do I need the cast or bitwise and?
I was originally going to file a bug but I think I'm just misunderstanding something fundamental.
There is a bug as well as a misunderstanding. # import std.stdio; # # int thirty_one = 31; # int thirty_two = 32; # int thirty_three = 33; # int two_neg = -2; # int four_neg = -4; # int i = -1; # uint u = -1; # # TypeInfo type_info(...){ # return _arguments[0]; # } # void info(char[] exp)(char[] comment = null){ # writef("0b%064b ", mixin(exp)); # writef("%s", typeof(mixin(exp)).stringof); # mixin("writefln(\"\t%s\", \"" ~ exp ~ "\");"); # if(comment.length){ # writefln("\t%s", comment); # } # } # # void main() { # info!("i"); # info!("u"); # info!("two_neg"); # writefln(); # info!("cast(long)two_neg << 32 | i"); # info!("cast(long)two_neg << 32 | u")("Why do they differ?"); # writefln(); # info!("two_neg << 32")("Huh? Let's try that again:"); # info!("two_neg"); # info!("two_neg << thirty_two"); # info!("(two_neg << 31) << 1"); # info!("(two_neg << 31) << 2"); # info!("two_neg << thirty_three"); # writefln(); # writefln("%s", "issue: shifting is implemented as\n" # "\t\tx << (shift % (sizeof(x) * 8))\n" # "\tinstead of\n" # "\t\tx << ((shift >= (sizeof(x) * 8)) ? (0) : (shift))"); # writefln("at least for cases where the shift width is known at compile time accepting \"sizeof(x) * 8\" is a bug"); # writefln(); # writefln("Let's try another approach:"); # info!("cast(long)two_neg << 32 | i"); # info!("cast(long)two_neg << 32 | u"); # info!("(cast(long)two_neg) << 32 | i"); # info!("(cast(long)two_neg) << 32 | u"); # info!("((cast(long)two_neg) << 32) | i"); # info!("((cast(long)two_neg) << 32) | u"); # info!("((cast(long)two_neg) << 32) | (cast(long)i)"); # info!("((cast(long)two_neg) << 32) | (cast(long)u)"); # info!("((cast(long)two_neg) << 32) | (cast(long)i)"); # info!("((cast(long)two_neg) << 32) | (cast(long)u)"); # writefln(); # info!("(cast(long)two_neg) << 32"); # info!("cast(long) 0xFFFFFFFE_00000000L"); # info!("(cast(long) 0xFFFFFFFE_00000000L) | i"); # info!("(cast(long) 0xFFFFFFFE_00000000L) | u"); # info!("cast(long) i"); # info!("cast(long) u"); # writefln(); # writefln("I hope the 2 lines below make sense now"); # info!("cast(long)two_neg << 32 | i"); # info!("cast(long)two_neg << 32 | u"); # }
Thanks for this, that clarifies it for me. Added a note to Bug 550. -- Remove ".doesnotlike.spam" from the mail address.
May 12 2007








Deewiant <deewiant.doesnotlike.spam gmail.com>