Thread overview | |||||
---|---|---|---|---|---|
|
May 11, 2007 Strange behaviour trying to bitwise or two negative ints into a long | ||||
---|---|---|---|---|
| ||||
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 Re: Strange behaviour trying to bitwise or two negative ints into a long | ||||
---|---|---|---|---|
| ||||
Posted in reply to Deewiant Attachments: | 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
|
May 12, 2007 Re: Strange behaviour trying to bitwise or two negative ints into a long | ||||
---|---|---|---|---|
| ||||
Posted in reply to Thomas Kuehne | 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. |
Copyright © 1999-2021 by the D Language Foundation