BitArray shift left/right confusion.

Biotronic simen.kjaras at gmail.com
Wed Dec 27 20:45:49 UTC 2017


On Wednesday, 27 December 2017 at 18:08:19 UTC, Bastiaan Veelo 
wrote:
> I suppose the following is not a bug, but confusing it is:
>
> ```
> void main()
> {
>     import std.stdio;
>     import std.bitmanip;
>     BitArray ba = [1, 1, 1, 1, 1, 1, 1, 1];
>     writeln(ba);	// [1, 1, 1, 1, 1, 1, 1, 1]
>     ba >>= 4;		// right shift
>     writeln(ba);	// [1, 1, 1, 1, 0, 0, 0, 0] bits shifted left
> }```
>
> I suppose this is because the array is printed left-to-right, 
> whereas the bits in a byte are typically ordered right-to-left. 
> I suppose I should interpret the bits in the array to increase 
> in significance with increasing index (little endian) and that 
> right-shift means a shift towards less significance (which is 
> to the right in big endian).
>
> The documentation of <<= and >>= [1] however just talks about 
> left and right, without defining left and right or clarifying 
> that the directions are reversed from how the array is printed.
>
> Is there something I have missed?
>
> [1] 
> https://dlang.org/phobos/std_bitmanip.html#.BitArray.opOpAssign.2

BitArray is apparently a mess. As you've pointed out it prints 
the bits in the wrong order. I won't mince words here, since D 
has binary literals on the form 0b10011110. Put that in a 
BitArray and print it with the format string "0b%b", and you'll 
get 0b01111001. While it may have been intentional, it's bug 
prone and confusing, and so definitely a bug.

It also fucks up royally when it has an exact multiple of 32 bits 
in its buffer, overwriting the last word with 0s when you try and 
shift it in any way.

It also doesn't remove set bits outside of its covered area when 
cast to size_t[]. That is, if I do 
cast(size_t[])(BitArray([1,1,1,1,1,1,1,1]) << 4), the result will 
be something like [4080], which corresponds to 
[0b0000_1111_1111_0000].

Lastly (and this is pointed out explicitly in the documentation, 
but still smells if you ask me), it will overwrite bits in the 
words it covers, even if it does not cover those exact bits.

The first two are definitely bugs. The last two are results of 
the intended use case for BitArray, I believe. The documentation 
doesn't explicitly point this out, but it seems BitArray is 
intended to give a bit-by-bit view of an area of memory that is 
actually some other type. Something like this:

struct S {
    int n;
    float f;
}

void foo(ref S s) {
     import std.bitmanip;
     auto a = BitArray((&s)[0..1], S.sizeof);
     a[7] = true; // Actually sets the corresponding bit in s.
}

--
   Biotronic


More information about the Digitalmars-d-learn mailing list