Thread overview
Strange behaviour trying to bitwise or two negative ints into a long
May 11, 2007
Deewiant
May 11, 2007
Thomas Kuehne
May 12, 2007
Deewiant
May 11, 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
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
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.