I was looking at the issues you reported and was pretty surprised
how some of the features work. So I'm going to revive this thread
with an explanation.
On Wednesday, 27 December 2017 at 20:45:49 UTC, Biotronic wrote:
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.
BitArray stores its data in a `size_t[]` array - on 64-bit it
consists of 8-byte units, each unit having its beginning at the
least significant bit. So it works as you would probably expect:
bool[128] bits;
auto ba = BitArray(bits); // one bool corresponds to one bit in
this constructor
ba[0] = 1;
ba[127] = 1;
Now, the exact representation of the array in this BitArray is as
follows:
index: | 0 | 1 |
bit no: | 64 ... 1 0 | 63 ... 1 0 |
values: | 0 ... 0 1 | 1 ... 0 0 |
You can get this array using cast:
size_t[] exact = cast(size_t[]) ba;
assert(exact[0] == 1);
assert(exact[1] == size_t(1) << 63);
Printing works in the human, i.e. logical, way:
writeln(ba); // [1, 0, ..., 0, ..., 0, 1]
BitArray has also a constructor taking a raw representation of
the underlying array:
size_t val = 0b1111_0000;
auto ba2 = BitArray([val], 8);
writeln(ba2); // [0, 0, 0, 0, 1, 1, 1, 1]
It may be surprising, as it's opposite order of the binary
literal. But this works as intended because it's supposed to be
the inversion of casting:
assert(cast(size_t[]) ba2 == [val]);
It also works like that e.g. in Java's BitSet and C++'s bitset.
On the other hand, shifting operators are equally confusing for
me, as they are for you - they really work in the other way
around! I thought this is a very weird bug, but I found this pull
request: https://github.com/dlang/phobos/pull/2844, which states
this is the intended behaviour.
I don't know if there is anybody that would expect this - it's
inconsistent with any other bitset implementation I know from
other languages, as well as with what logic suggests. I'm curious
if the authors changed their minds in this regard and there is
any chance for that to be rewritten?
And besides, it's pretty bugged, indeed.